diff options
| -rw-r--r-- | src/reel.cc | 28 | ||||
| -rw-r--r-- | src/reel.h | 9 | ||||
| -rw-r--r-- | src/sound_asset.h | 4 | ||||
| -rw-r--r-- | test/kdm_test.cc | 91 | ||||
| -rw-r--r-- | test/test.cc | 26 | ||||
| -rw-r--r-- | test/test.h | 25 | ||||
| -rw-r--r-- | test/verify_test.cc | 2 |
7 files changed, 158 insertions, 27 deletions
diff --git a/src/reel.cc b/src/reel.cc index daa1067c..cca62ed8 100644 --- a/src/reel.cc +++ b/src/reel.cc @@ -312,28 +312,38 @@ Reel::all_encrypted () const void Reel::add (DecryptedKDM const & kdm) { - auto keys = kdm.keys (); + give_kdm_to_assets (kdm); + /* We have to keep the KDMs that we are given, as they will not be passed to unresolved assets. + * After we resolve some assets we will re-call give_kdm_to_assets() with all the KDMs that + * we have been given so far. + */ + _kdms.push_back (kdm); +} + - for (auto const& i: keys) { - if (_main_picture && i.id() == _main_picture->key_id()) { +void +Reel::give_kdm_to_assets (DecryptedKDM const & kdm) +{ + for (auto const& i: kdm.keys()) { + if (_main_picture && i.id() == _main_picture->key_id() && _main_picture->asset_ref().resolved()) { _main_picture->asset()->set_key (i.key()); } - if (_main_sound && i.id() == _main_sound->key_id()) { + if (_main_sound && i.id() == _main_sound->key_id() && _main_sound->asset_ref().resolved()) { _main_sound->asset()->set_key (i.key()); } if (_main_subtitle) { auto smpte = dynamic_pointer_cast<ReelSMPTESubtitleAsset>(_main_subtitle); - if (smpte && i.id() == smpte->key_id()) { + if (smpte && i.id() == smpte->key_id() && smpte->asset_ref().resolved()) { smpte->smpte_asset()->set_key(i.key()); } } for (auto j: _closed_captions) { auto smpte = dynamic_pointer_cast<ReelSMPTESubtitleAsset>(j); - if (smpte && i.id() == smpte->key_id()) { + if (smpte && i.id() == smpte->key_id() && smpte->asset_ref().resolved()) { smpte->smpte_asset()->set_key(i.key()); } } - if (_atmos && i.id() == _atmos->key_id()) { + if (_atmos && i.id() == _atmos->key_id() && _atmos->asset_ref().resolved()) { _atmos->asset()->set_key (i.key()); } } @@ -424,6 +434,10 @@ Reel::resolve_refs (vector<shared_ptr<Asset>> assets) if (_atmos) { _atmos->asset_ref().resolve (assets); } + + for (auto const& i: _kdms) { + give_kdm_to_assets (i); + } } @@ -41,11 +41,12 @@ #define LIBDCP_REEL_H +#include "decrypted_kdm.h" #include "key.h" -#include "types.h" #include "ref.h" -#include <memory> +#include "types.h" #include <boost/function.hpp> +#include <memory> namespace cxml { @@ -136,12 +137,16 @@ public: void resolve_refs (std::vector<std::shared_ptr<Asset>>); private: + void give_kdm_to_assets (dcp::DecryptedKDM const& kdm); + std::shared_ptr<ReelPictureAsset> _main_picture; std::shared_ptr<ReelSoundAsset> _main_sound; std::shared_ptr<ReelSubtitleAsset> _main_subtitle; std::shared_ptr<ReelMarkersAsset> _main_markers; std::vector<std::shared_ptr<ReelClosedCaptionAsset>> _closed_captions; std::shared_ptr<ReelAtmosAsset> _atmos; + + std::vector<dcp::DecryptedKDM> _kdms; }; } diff --git a/src/sound_asset.h b/src/sound_asset.h index 799e671c..c943d88b 100644 --- a/src/sound_asset.h +++ b/src/sound_asset.h @@ -55,7 +55,7 @@ namespace dcp { extern std::shared_ptr<dcp::SoundAsset> simple_sound ( - boost::filesystem::path path, std::string suffix, dcp::MXFMetadata mxf_meta, std::string language, int frames, int sample_rate + boost::filesystem::path path, std::string suffix, dcp::MXFMetadata mxf_meta, std::string language, int frames, int sample_rate, boost::optional<dcp::Key> ); @@ -112,7 +112,7 @@ public: private: friend class SoundAssetWriter; friend std::shared_ptr<dcp::SoundAsset> (::simple_sound) ( - boost::filesystem::path path, std::string suffix, dcp::MXFMetadata mxf_meta, std::string language, int frames, int sample_rate + boost::filesystem::path path, std::string suffix, dcp::MXFMetadata mxf_meta, std::string language, int frames, int sample_rate, boost::optional<dcp::Key> ); std::string pkl_type (Standard standard) const override { diff --git a/test/kdm_test.cc b/test/kdm_test.cc index 5b0ae622..d5cd456f 100644 --- a/test/kdm_test.cc +++ b/test/kdm_test.cc @@ -40,6 +40,9 @@ #include "picture_asset_writer.h" #include "reel.h" #include "reel_mono_picture_asset.h" +#include "reel_sound_asset.h" +#include "reel_smpte_subtitle_asset.h" +#include "smpte_subtitle_asset.h" #include "test.h" #include "types.h" #include "util.h" @@ -51,11 +54,11 @@ LIBDCP_ENABLE_WARNINGS #include <boost/test/unit_test.hpp> -using std::list; -using std::string; -using std::vector; +using std::dynamic_pointer_cast; using std::make_shared; using std::shared_ptr; +using std::string; +using std::vector; using boost::optional; @@ -296,3 +299,85 @@ BOOST_AUTO_TEST_CASE (validity_period_test1) dcp::BadKDMDateError ); } + + +/** Test the case where we have: + * - a OV + VF + * - a single KDM which has keys for both OV and VF assets + * and we load VF, then KDM, then the OV. The OV's assets should have their + * KDMs properly assigned. + */ +BOOST_AUTO_TEST_CASE (vf_kdm_test) +{ + /* Make OV */ + + boost::filesystem::path const ov_path = "build/test/vf_kdm_test_ov"; + boost::filesystem::path const vf_path = "build/test/vf_kdm_test_vf"; + dcp::Key key; + + auto ov = make_simple(ov_path, 1, 48, dcp::Standard::SMPTE, key); + ov->write_xml (); + + auto ov_reel = ov->cpls()[0]->reels()[0]; + auto ov_reel_picture = make_shared<dcp::ReelMonoPictureAsset>(dynamic_pointer_cast<dcp::ReelMonoPictureAsset>(ov_reel->main_picture())->mono_asset(), 0); + auto ov_reel_sound = make_shared<dcp::ReelSoundAsset>(ov_reel->main_sound()->asset(), 0); + + /* Make VF */ + + auto subs = make_shared<dcp::SMPTESubtitleAsset>(); + subs->add(simple_subtitle()); + subs->set_key(key); + + boost::filesystem::remove_all (vf_path); + boost::filesystem::create_directory (vf_path); + dcp::ArrayData data(4096); + subs->add_font ("afont", data); + subs->write (vf_path / "subs.xml"); + + auto reel_subs = make_shared<dcp::ReelSMPTESubtitleAsset>(subs, dcp::Fraction(24, 1), 192, 0); + + auto reel = make_shared<dcp::Reel>(ov_reel_picture, ov_reel_sound, reel_subs); + + auto cpl = make_shared<dcp::CPL>("A Test DCP", dcp::ContentKind::TRAILER, dcp::Standard::SMPTE); + cpl->add (reel); + + auto vf = make_shared<dcp::DCP>("build/test/vf_kdm_test_vf"); + vf->add (cpl); + vf->write_xml (); + + /* Make KDM for VF */ + + auto kdm = dcp::DecryptedKDM( + cpl, + key, + dcp::LocalTime ("2016-01-01T00:00:00+00:00"), + dcp::LocalTime ("2017-01-08T00:00:00+00:00"), + "libdcp", + "test", + "2012-07-17T04:45:18+00:00" + ); + + /* Decrypt VF with the KDM */ + + dcp::DCP reload_vf(vf_path); + reload_vf.read(); + reload_vf.add (kdm); + + /* Add the OV */ + + dcp::DCP reload_ov(ov_path); + reload_ov.read(); + reload_vf.resolve_refs(reload_ov.assets()); + + /* Check that we can decrypt the VF */ + + BOOST_REQUIRE_EQUAL(reload_vf.cpls().size(), 1U); + BOOST_REQUIRE_EQUAL(reload_vf.cpls()[0]->reels().size(), 1U); + BOOST_REQUIRE(reload_vf.cpls()[0]->reels()[0]->main_picture()); + BOOST_REQUIRE(reload_vf.cpls()[0]->reels()[0]->main_picture()->asset()); + auto mono_asset = dynamic_pointer_cast<dcp::MonoPictureAsset>(reload_vf.cpls()[0]->reels()[0]->main_picture()->asset()); + BOOST_REQUIRE(mono_asset); + auto reader = mono_asset->start_read(); + reader->set_check_hmac(false); + reader->get_frame(0)->xyz_image(); +} diff --git a/test/test.cc b/test/test.cc index 3cb40aaf..f946c5dc 100644 --- a/test/test.cc +++ b/test/test.cc @@ -266,16 +266,19 @@ RNGFixer::~RNGFixer () shared_ptr<dcp::MonoPictureAsset> -simple_picture (boost::filesystem::path path, string suffix, int frames) +simple_picture (boost::filesystem::path path, string suffix, int frames, optional<dcp::Key> key) { dcp::MXFMetadata mxf_meta; mxf_meta.company_name = "OpenDCP"; mxf_meta.product_name = "OpenDCP"; mxf_meta.product_version = "0.0.25"; - shared_ptr<dcp::MonoPictureAsset> mp (new dcp::MonoPictureAsset (dcp::Fraction (24, 1), dcp::Standard::SMPTE)); + auto mp = make_shared<dcp::MonoPictureAsset>(dcp::Fraction (24, 1), dcp::Standard::SMPTE); mp->set_metadata (mxf_meta); - shared_ptr<dcp::PictureAssetWriter> picture_writer = mp->start_write (path / dcp::String::compose("video%1.mxf", suffix), false); + if (key) { + mp->set_key (*key); + } + auto picture_writer = mp->start_write (path / dcp::String::compose("video%1.mxf", suffix), false); dcp::Size const size (1998, 1080); auto image = make_shared<dcp::OpenJPEGImage>(size); @@ -294,12 +297,15 @@ simple_picture (boost::filesystem::path path, string suffix, int frames) shared_ptr<dcp::SoundAsset> -simple_sound (boost::filesystem::path path, string suffix, dcp::MXFMetadata mxf_meta, string language, int frames, int sample_rate) +simple_sound (boost::filesystem::path path, string suffix, dcp::MXFMetadata mxf_meta, string language, int frames, int sample_rate, optional<dcp::Key> key) { int const channels = 6; /* Set a valid language, then overwrite it, so that the language parameter can be badly formed */ - shared_ptr<dcp::SoundAsset> ms (new dcp::SoundAsset(dcp::Fraction(24, 1), sample_rate, channels, dcp::LanguageTag("en-US"), dcp::Standard::SMPTE)); + auto ms = make_shared<dcp::SoundAsset>(dcp::Fraction(24, 1), sample_rate, channels, dcp::LanguageTag("en-US"), dcp::Standard::SMPTE); + if (key) { + ms->set_key (*key); + } ms->_language = language; ms->set_metadata (mxf_meta); shared_ptr<dcp::SoundAssetWriter> sound_writer = ms->start_write (path / dcp::String::compose("audio%1.mxf", suffix)); @@ -327,7 +333,7 @@ simple_sound (boost::filesystem::path path, string suffix, dcp::MXFMetadata mxf_ shared_ptr<dcp::DCP> -make_simple (boost::filesystem::path path, int reels, int frames, dcp::Standard standard) +make_simple (boost::filesystem::path path, int reels, int frames, dcp::Standard standard, optional<dcp::Key> key) { /* Some known metadata */ dcp::MXFMetadata mxf_meta; @@ -335,6 +341,8 @@ make_simple (boost::filesystem::path path, int reels, int frames, dcp::Standard mxf_meta.product_name = "OpenDCP"; mxf_meta.product_version = "0.0.25"; + auto constexpr sample_rate = 48000; + boost::filesystem::remove_all (path); boost::filesystem::create_directories (path); auto d = make_shared<dcp::DCP>(path); @@ -347,7 +355,7 @@ make_simple (boost::filesystem::path path, int reels, int frames, dcp::Standard dcp::ContentVersion("urn:uuid:75ac29aa-42ac-1234-ecae-49251abefd11", "content-version-label-text") ); cpl->set_main_sound_configuration("51/L,R,C,LFE,Ls,Rs"); - cpl->set_main_sound_sample_rate(48000); + cpl->set_main_sound_sample_rate(sample_rate); cpl->set_main_picture_stored_area(dcp::Size(1998, 1080)); cpl->set_main_picture_active_area(dcp::Size(1998, 1080)); cpl->set_version_number(1); @@ -355,8 +363,8 @@ make_simple (boost::filesystem::path path, int reels, int frames, dcp::Standard for (int i = 0; i < reels; ++i) { string suffix = reels == 1 ? "" : dcp::String::compose("%1", i); - shared_ptr<dcp::MonoPictureAsset> mp = simple_picture (path, suffix, frames); - shared_ptr<dcp::SoundAsset> ms = simple_sound (path, suffix, mxf_meta, "en-US", frames); + auto mp = simple_picture (path, suffix, frames, key); + auto ms = simple_sound (path, suffix, mxf_meta, "en-US", frames, sample_rate, key); auto reel = make_shared<dcp::Reel>( shared_ptr<dcp::ReelMonoPictureAsset>(new dcp::ReelMonoPictureAsset(mp, 0)), diff --git a/test/test.h b/test/test.h index 8733c7c3..339dd8aa 100644 --- a/test/test.h +++ b/test/test.h @@ -43,11 +43,30 @@ extern boost::filesystem::path xsd_test; extern void check_xml (xmlpp::Element* ref, xmlpp::Element* test, std::vector<std::string> ignore_tags, bool ignore_whitespace = false); extern void check_xml (std::string ref, std::string test, std::vector<std::string> ignore, bool ignore_whitespace = false); extern void check_file (boost::filesystem::path ref, boost::filesystem::path check); -extern std::shared_ptr<dcp::MonoPictureAsset> simple_picture (boost::filesystem::path path, std::string suffix, int frames = 24); -extern std::shared_ptr<dcp::SoundAsset> simple_sound (boost::filesystem::path path, std::string suffix, dcp::MXFMetadata mxf_meta, std::string language, int frames = 24, int sample_rate = 48000); +extern std::shared_ptr<dcp::MonoPictureAsset> simple_picture ( + boost::filesystem::path path, + std::string suffix, + int frames = 24, + boost::optional<dcp::Key> key = boost::optional<dcp::Key>() + ); +extern std::shared_ptr<dcp::SoundAsset> simple_sound ( + boost::filesystem::path path, + std::string suffix, + dcp::MXFMetadata mxf_meta, + std::string language, + int frames = 24, + int sample_rate = 48000, + boost::optional<dcp::Key> key = boost::optional<dcp::Key>() + ); extern std::shared_ptr<dcp::Subtitle> simple_subtitle (); extern std::shared_ptr<dcp::ReelMarkersAsset> simple_markers (int frames = 24); -extern std::shared_ptr<dcp::DCP> make_simple (boost::filesystem::path path, int reels = 1, int frames = 24, dcp::Standard = dcp::Standard::SMPTE); +extern std::shared_ptr<dcp::DCP> make_simple ( + boost::filesystem::path path, + int reels = 1, + int frames = 24, + dcp::Standard = dcp::Standard::SMPTE, + boost::optional<dcp::Key> key = boost::optional<dcp::Key>() + ); extern std::shared_ptr<dcp::DCP> make_simple_with_interop_subs (boost::filesystem::path path); extern std::shared_ptr<dcp::DCP> make_simple_with_smpte_subs (boost::filesystem::path path); extern std::shared_ptr<dcp::DCP> make_simple_with_interop_ccaps (boost::filesystem::path path); diff --git a/test/verify_test.cc b/test/verify_test.cc index 62bb7f31..707eed21 100644 --- a/test/verify_test.cc +++ b/test/verify_test.cc @@ -1961,7 +1961,7 @@ BOOST_AUTO_TEST_CASE (verify_invalid_sound_frame_rate) auto reel_picture = make_shared<dcp::ReelMonoPictureAsset>(picture, 0); auto reel = make_shared<dcp::Reel>(); reel->add (reel_picture); - auto sound = simple_sound (dir, "foo", dcp::MXFMetadata(), "de-DE", 24, 96000); + auto sound = simple_sound (dir, "foo", dcp::MXFMetadata(), "de-DE", 24, 96000, boost::none); auto reel_sound = make_shared<dcp::ReelSoundAsset>(sound, 0); reel->add (reel_sound); reel->add (simple_markers()); |
