Calculate hashes for any referenced assets that do not already have one.
authorCarl Hetherington <cth@carlh.net>
Tue, 24 Nov 2020 00:29:11 +0000 (01:29 +0100)
committerCarl Hetherington <cth@carlh.net>
Thu, 26 Nov 2020 00:49:33 +0000 (01:49 +0100)
This is necessary so that we always include <Hash> in CPLs even
when referencing DCPs that do not have it.

cscript
src/lib/writer.cc
src/lib/writer.h
test/cpl_hash_test.cc [new file with mode: 0644]
test/wscript

diff --git a/cscript b/cscript
index 59a7cdd303ec3e470ee2627996dd3258d5104e7d..1d206dbfd94f96af21596c21a86261ea77fc57a0 100644 (file)
--- a/cscript
+++ b/cscript
@@ -370,8 +370,8 @@ def dependencies(target, options):
             (target.platform == 'osx' and target.bits == 64) or
             (target.platform == 'windows')) else {}
 
-    deps.append(('libdcp', 'e78b38b', cpp_lib_options))
-    deps.append(('libsub', 'c7e7bf3', cpp_lib_options))
+    deps.append(('libdcp', 'c9865a3', cpp_lib_options))
+    deps.append(('libsub', 'b0413a7', cpp_lib_options))
     deps.append(('leqm-nrt', 'carl'))
     deps.append(('rtaudio', 'carl'))
     # We get our OpenSSL libraries from the environment, but we
index a9700f4f5edbbb7272e2ed2735c56f74cd2535b3..4915fe68dd21fe9f9639ddae4bca76673e700800 100644 (file)
@@ -38,6 +38,7 @@
 #include "text_content.h"
 #include <dcp/cpl.h>
 #include <dcp/locale_convert.h>
+#include <dcp/reel_mxf.h>
 #include <boost/foreach.hpp>
 #include <fstream>
 #include <cerrno>
@@ -557,10 +558,11 @@ Writer::finish ()
                pool.create_thread (boost::bind (&boost::asio::io_service::run, &service));
        }
 
+       boost::function<void (float)> set_progress = boost::bind (&Writer::set_digest_progress, this, job.get(), _1);
        BOOST_FOREACH (ReelWriter& i, _reels) {
-               boost::function<void (float)> set_progress = boost::bind (&Writer::set_digest_progress, this, job.get(), _1);
                service.post (boost::bind (&ReelWriter::calculate_digests, &i, set_progress));
        }
+       service.post (boost::bind (&Writer::calculate_referenced_digests, this, set_progress));
 
        work.reset ();
        pool.join_all ();
@@ -849,3 +851,18 @@ Writer::set_digest_progress (Job* job, float progress)
        Waker waker;
        waker.nudge ();
 }
+
+
+/** Calculate hashes for any referenced MXF assets which do not already have one */
+void
+Writer::calculate_referenced_digests (boost::function<void (float)> set_progress)
+{
+       BOOST_FOREACH (ReferencedReelAsset const& i, _reel_assets) {
+               shared_ptr<dcp::ReelMXF> mxf = dynamic_pointer_cast<dcp::ReelMXF>(i.asset);
+               if (mxf && !mxf->hash()) {
+                       mxf->asset_ref().asset()->hash (set_progress);
+                       mxf->set_hash (mxf->asset_ref().asset()->hash());
+               }
+       }
+}
+
index 459bc5a882e18e10bb541f4b33e91c7c65eda72c..4c22ef48e13acd0bd4e8598cacf1fff178104377 100644 (file)
@@ -125,6 +125,7 @@ private:
        size_t video_reel (int frame) const;
        void set_digest_progress (Job* job, float progress);
        void write_cover_sheet ();
+       void calculate_referenced_digests (boost::function<void (float)> set_progress);
 
        /** our Film */
        boost::shared_ptr<const Film> _film;
diff --git a/test/cpl_hash_test.cc b/test/cpl_hash_test.cc
new file mode 100644 (file)
index 0000000..28a9420
--- /dev/null
@@ -0,0 +1,97 @@
+/*
+    Copyright (C) 2020 Carl Hetherington <cth@carlh.net>
+
+    This file is part of DCP-o-matic.
+
+    DCP-o-matic 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.
+
+    DCP-o-matic 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 DCP-o-matic.  If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+/** @file  test/cpl_hash_test.cc
+ *  @brief Make sure that <Hash> tags are always written to CPLs where required.
+ *  @ingroup feature
+ */
+
+
+#include "lib/content_factory.h"
+#include "lib/cross.h"
+#include "lib/dcp_content.h"
+#include "lib/film.h"
+#include "test.h"
+#include <boost/algorithm/string.hpp>
+#include <boost/test/unit_test.hpp>
+
+
+using std::string;
+using boost::shared_ptr;
+
+
+BOOST_AUTO_TEST_CASE (hash_added_to_imported_dcp_test)
+{
+       using namespace boost::filesystem;
+
+       string const ov_name = "hash_added_to_imported_dcp_test_ov";
+       shared_ptr<Film> ov = new_test_film2 (ov_name);
+       ov->examine_and_add_content (content_factory("test/data/flat_red.png").front());
+       BOOST_REQUIRE (!wait_for_jobs());
+       ov->make_dcp();
+       BOOST_REQUIRE (!wait_for_jobs());
+
+       /* Remove <Hash> tags from the CPL */
+       for (directory_iterator i = directory_iterator(String::compose("build/test/%1/%2", ov_name, ov->dcp_name())); i != directory_iterator(); ++i) {
+               if (boost::algorithm::starts_with(i->path().filename().string(), "cpl_")) {
+                       FILE* in = fopen_boost(i->path(), "r");
+                       BOOST_REQUIRE (in);
+                       FILE* out = fopen_boost(i->path().string() + ".tmp", "w");
+                       BOOST_REQUIRE (out);
+                       char buffer[256];
+                       while (fgets (buffer, sizeof(buffer), in)) {
+                               if (string(buffer).find("Hash") == string::npos) {
+                                       fputs (buffer, out);
+                               }
+                       }
+                       fclose (in);
+                       fclose (out);
+                       rename (i->path().string() + ".tmp", i->path());
+               }
+       }
+
+       string const vf_name = "hash_added_to_imported_dcp_test_vf";
+       shared_ptr<Film> vf = new_test_film2 (vf_name);
+       shared_ptr<DCPContent> ov_content(new DCPContent(String::compose("build/test/%1/%2", ov_name, ov->dcp_name())));
+       vf->examine_and_add_content (ov_content);
+       BOOST_REQUIRE (!wait_for_jobs());
+
+       ov_content->set_reference_video (true);
+       vf->make_dcp ();
+       BOOST_REQUIRE (!wait_for_jobs());
+
+       /* Check for Hash tags in the VF DCP */
+       int hashes = 0;
+       for (directory_iterator i = directory_iterator(String::compose("build/test/%1/%2", vf_name, vf->dcp_name())); i != directory_iterator(); ++i) {
+               if (boost::algorithm::starts_with(i->path().filename().string(), "cpl_")) {
+                       FILE* in = fopen_boost(i->path(), "r");
+                       BOOST_REQUIRE (in);
+                       char buffer[256];
+                       while (fgets (buffer, sizeof(buffer), in)) {
+                               if (string(buffer).find("Hash") != string::npos) {
+                                       ++hashes;
+                               }
+                       }
+                       fclose (in);
+               }
+       }
+       BOOST_CHECK_EQUAL (hashes, 2);
+}
+
index 39b96e39defe8fbdad6c6f7a737381ea0b5ebe1e..9037b62273b6fa10ba5dddbb7ca1284436b3ecda 100644 (file)
@@ -60,6 +60,7 @@ def build(bld):
                  colour_conversion_test.cc
                  config_test.cc
                  content_test.cc
+                 cpl_hash_test.cc
                  create_cli_test.cc
                  crypto_test.cc
                  dcpomatic_time_test.cc