From 58e94d1c412cd87a28fca99b46c7d5cf408f8186 Mon Sep 17 00:00:00 2001 From: Carl Hetherington Date: Mon, 3 Jan 2022 00:11:16 +0000 Subject: [PATCH] Fix creation of dcpdig files in projects that make VFs (#2109). Previously we would always get keys from the project which was wrong with assets that already have their own key. --- src/lib/dcp_digest_file.cc | 12 +++---- src/lib/dcp_transcode_job.cc | 29 +++++++++++++--- test/dcp_digest_file_test.cc | 65 ++++++++++++++++++++++++++++++++++++ 3 files changed, 96 insertions(+), 10 deletions(-) diff --git a/src/lib/dcp_digest_file.cc b/src/lib/dcp_digest_file.cc index b178e3da7..0ea5ae821 100644 --- a/src/lib/dcp_digest_file.cc +++ b/src/lib/dcp_digest_file.cc @@ -39,7 +39,7 @@ using std::string; template -void add_asset(string key, shared_ptr reel_asset, shared_ptr asset, xmlpp::Element* reel, string name) +void add_asset(string film_key, shared_ptr reel_asset, shared_ptr asset, xmlpp::Element* reel, string name) { if (asset) { auto out = reel->add_child(name); @@ -49,7 +49,7 @@ void add_asset(string key, shared_ptr reel_asset, shared_ptr asset, xmlpp: } if (asset->key_id()) { out->add_child("KeyId")->add_child_text("urn:uuid:" + asset->key_id().get()); - out->add_child("Key")->add_child_text(key); + out->add_child("Key")->add_child_text(asset->key() ? asset->key()->hex() : film_key); } } }; @@ -59,7 +59,7 @@ void write_dcp_digest_file ( boost::filesystem::path path, shared_ptr cpl, - string key + string film_key ) { xmlpp::Document doc; @@ -75,13 +75,13 @@ write_dcp_digest_file ( out_reel->add_child("Id")->add_child_text("urn:uuid:" + in_reel->id()); out_reel->add_child("AnnotationText"); if (in_reel->main_picture()) { - add_asset(key, in_reel->main_picture(), in_reel->main_picture()->asset(), out_reel, "MainPicture"); + add_asset(film_key, in_reel->main_picture(), in_reel->main_picture()->asset(), out_reel, "MainPicture"); } if (in_reel->main_sound()) { - add_asset(key, in_reel->main_sound(), in_reel->main_sound()->asset(), out_reel, "MainSound"); + add_asset(film_key, in_reel->main_sound(), in_reel->main_sound()->asset(), out_reel, "MainSound"); } if (auto smpte_sub = dynamic_pointer_cast(in_reel->main_subtitle())) { - add_asset(key, smpte_sub, smpte_sub->smpte_asset(), out_reel, "MainSubtitle"); + add_asset(film_key, smpte_sub, smpte_sub->smpte_asset(), out_reel, "MainSubtitle"); } } doc.write_to_file_formatted(path.string()); diff --git a/src/lib/dcp_transcode_job.cc b/src/lib/dcp_transcode_job.cc index ae3f3f837..dd7b7d624 100644 --- a/src/lib/dcp_transcode_job.cc +++ b/src/lib/dcp_transcode_job.cc @@ -30,8 +30,10 @@ #include +using std::dynamic_pointer_cast; using std::make_shared; using std::shared_ptr; +using std::vector; DCPTranscodeJob::DCPTranscodeJob (shared_ptr film, ChangedBehaviour changed) @@ -48,11 +50,30 @@ DCPTranscodeJob::post_transcode () JobManager::instance()->add(make_shared(_film)); } - dcp::DCP dcp(_film->dir(_film->dcp_name())); - dcp.read(); + /* The first directory is the project's DCP, so the first CPL will also be from the project + * (not from one of the DCPs imported into the project). + */ + vector all_directories = { _film->dir(_film->dcp_name()) }; + + vector all_kdms; + for (auto content: _film->content()) { + if (auto dcp_content = dynamic_pointer_cast(content)) { + auto directories = dcp_content->directories(); + std::copy (directories.begin(), directories.end(), std::back_inserter(all_directories)); + if (dcp_content->kdm()) { + all_kdms.push_back (dcp_content->kdm().get()); + } + } + } + + auto cpls = dcp::find_and_resolve_cpls (all_directories, true); + DCPOMATIC_ASSERT (!cpls.empty()); + auto cpl = cpls.front (); - for (auto cpl: dcp.cpls()) { - write_dcp_digest_file (_film->file(cpl->annotation_text().get_value_or(cpl->id()) + ".dcpdig"), cpl, _film->key().hex()); + for (auto const& kdm: all_kdms) { + cpl->add (decrypt_kdm_with_helpful_error(kdm)); } + + write_dcp_digest_file (_film->file(cpl->annotation_text().get_value_or(cpl->id()) + ".dcpdig"), cpl, _film->key().hex()); } diff --git a/test/dcp_digest_file_test.cc b/test/dcp_digest_file_test.cc index 85928b6bb..becfd4317 100644 --- a/test/dcp_digest_file_test.cc +++ b/test/dcp_digest_file_test.cc @@ -19,14 +19,24 @@ */ +#include "lib/config.h" #include "lib/content_factory.h" +#include "lib/dcp_content.h" #include "lib/dcp_digest_file.h" #include "lib/film.h" #include "test.h" +#include #include +#include #include +using std::ifstream; +using std::make_shared; +using std::string; +using boost::optional; + + BOOST_AUTO_TEST_CASE (dcp_digest_file_test) { dcp::DCP dcp("test/data/dcp_digest_test_dcp"); @@ -38,3 +48,58 @@ BOOST_AUTO_TEST_CASE (dcp_digest_file_test) check_xml ("test/data/digest.xml", "build/test/digest.xml", {}); } + +BOOST_AUTO_TEST_CASE (dcp_digest_file_test2) +{ + auto get_key_from_digest = [](boost::filesystem::path filename) -> optional { + ifstream digest(filename.string().c_str()); + while (digest.good()) { + string line; + getline (digest, line); + boost::algorithm::trim (line); + if (boost::starts_with(line, "") && line.length() > 37) { + return line.substr(5, 32); + } + } + + return {}; + }; + + auto red = content_factory("test/data/flat_red.png").front(); + auto ov = new_test_film2 ("dcp_digest_file_test2_ov", { red }); + ov->set_encrypted (true); + make_and_verify_dcp (ov); + + auto ov_key_check = get_key_from_digest ("build/test/dcp_digest_file_test2_ov/" + ov->dcp_name() + ".dcpdig"); + BOOST_REQUIRE (static_cast(ov_key_check)); + BOOST_CHECK_EQUAL (*ov_key_check, ov->key().hex()); + + dcp::DCP find_cpl (ov->dir(ov->dcp_name())); + find_cpl.read (); + BOOST_REQUIRE (!find_cpl.cpls().empty()); + auto ov_cpl = find_cpl.cpls()[0]->file(); + BOOST_REQUIRE (static_cast(ov_cpl)); + + auto kdm = ov->make_kdm ( + Config::instance()->decryption_chain()->leaf(), + {}, + ov_cpl.get(), + dcp::LocalTime(), dcp::LocalTime(), + dcp::Formulation::MODIFIED_TRANSITIONAL_1, + true, + 0 + ); + + auto ov_dcp = make_shared(ov->dir(ov->dcp_name())); + ov_dcp->add_kdm (kdm); + ov_dcp->set_reference_video (true); + ov_dcp->set_reference_audio (true); + auto vf = new_test_film2 ("dcp_digest_file_test2_vf", { ov_dcp }); + vf->set_encrypted (true); + make_and_verify_dcp (vf, {dcp::VerificationNote::Code::EXTERNAL_ASSET}); + + auto vf_key_check = get_key_from_digest ("build/test/dcp_digest_file_test2_vf/" + vf->dcp_name() + ".dcpdig"); + BOOST_REQUIRE (static_cast(vf_key_check)); + BOOST_CHECK_EQUAL (*vf_key_check, ov->key().hex()); +} + -- 2.30.2