Allow DCP content to store and serialise metadata.
authorCarl Hetherington <cth@carlh.net>
Tue, 21 Apr 2020 21:32:42 +0000 (23:32 +0200)
committerCarl Hetherington <cth@carlh.net>
Tue, 21 Apr 2020 21:51:38 +0000 (23:51 +0200)
src/lib/dcp_content.cc
src/lib/dcp_content.h
src/lib/dcp_examiner.cc
src/lib/dcp_examiner.h
test/import_dcp_test.cc

index 6c2db91d3bbcbb093f89a8fabba5bc4a65023d56..4280ad13aa7474b698a5255c3e2e635216d15ba2 100644 (file)
@@ -151,6 +151,12 @@ DCPContent::DCPContent (cxml::ConstNodePtr node, int version)
        BOOST_FOREACH (cxml::ConstNodePtr i, node->node_children("Marker")) {
                _markers[dcp::marker_from_string(i->string_attribute("type"))] = ContentTime(raw_convert<int64_t>(i->content()));
        }
+
+       BOOST_FOREACH (cxml::ConstNodePtr i, node->node_children("Rating")) {
+               _ratings.push_back (dcp::Rating(i));
+       }
+
+       _content_version = node->optional_string_child("ContentVersion").get_value_or("");
 }
 
 void
@@ -249,6 +255,8 @@ DCPContent::examine (shared_ptr<const Film> film, shared_ptr<Job> job)
                for (map<dcp::Marker, dcp::Time>::const_iterator i = markers.begin(); i != markers.end(); ++i) {
                        _markers[i->first] = ContentTime(i->second.as_editable_units(DCPTime::HZ));
                }
+               _ratings = examiner->ratings ();
+               _content_version = examiner->content_version ();
        }
 
        if (old_texts == texts) {
@@ -354,6 +362,13 @@ DCPContent::as_xml (xmlpp::Node* node, bool with_paths) const
                marker->set_attribute("type", dcp::marker_to_string(i->first));
                marker->add_child_text(raw_convert<string>(i->second.get()));
        }
+
+       BOOST_FOREACH (dcp::Rating i, _ratings) {
+               xmlpp::Element* rating = node->add_child("Rating");
+               i.as_xml (rating);
+       }
+
+       node->add_child("ContentVersion")->add_child_text (_content_version);
 }
 
 DCPTime
index 8658ac5ed83e3358094709f1166215aabe9004f9..6d707670f27eb6bc267d98cefe7bbcd487cdc31f 100644 (file)
@@ -158,6 +158,14 @@ public:
 
        Resolution resolution () const;
 
+       std::vector<dcp::Rating> ratings () const {
+               return _ratings;
+       }
+
+       std::string content_version () const {
+               return _content_version;
+       }
+
 private:
        friend class reels_test5;
 
@@ -205,6 +213,8 @@ private:
        /** List of the lengths of the reels in this DCP */
        std::list<int64_t> _reel_lengths;
        std::map<dcp::Marker, dcpomatic::ContentTime> _markers;
+       std::vector<dcp::Rating> _ratings;
+       std::string _content_version;
 };
 
 #endif
index a7d451eca75e14d326ea82d527a5e090b30e1782..d04dacdd6ca573ec7afbf8975b020f2c8d6277ae 100644 (file)
@@ -23,6 +23,7 @@
 #include "exceptions.h"
 #include "image.h"
 #include "config.h"
+#include "util.h"
 #include <dcp/dcp.h>
 #include <dcp/decrypted_kdm.h>
 #include <dcp/cpl.h>
@@ -236,6 +237,8 @@ DCPExaminer::DCPExaminer (shared_ptr<const DCPContent> content, bool tolerant)
        _standard = cpl->standard().get();
        _three_d = !cpl->reels().empty() && cpl->reels().front()->main_picture() &&
                dynamic_pointer_cast<dcp::StereoPictureAsset> (cpl->reels().front()->main_picture()->asset());
+       _ratings = list_to_vector (cpl->ratings());
+       _content_version = cpl->content_version_label_text ();
 
        _cpl = cpl->id ();
 }
index c1ba54deed3c34f29d52ed980a6f68c6f5a704ea..21aa8d3ab58537de5c4446f899f94d4bcc4bb459 100644 (file)
@@ -123,6 +123,14 @@ public:
                return _markers;
        }
 
+       std::vector<dcp::Rating> ratings () const {
+               return _ratings;
+       }
+
+       std::string content_version () const {
+               return _content_version;
+       }
+
 private:
        boost::optional<double> _video_frame_rate;
        boost::optional<dcp::Size> _video_size;
@@ -146,4 +154,6 @@ private:
        std::string _cpl;
        std::list<int64_t> _reel_lengths;
        std::map<dcp::Marker, dcp::Time> _markers;
+       std::vector<dcp::Rating> _ratings;
+       std::string _content_version;
 };
index 4c227ac34aea35cd81764062d0489aa0f6c6c6fc..83dd0c6de043b8b35803e6b65987e3d1109fae38 100644 (file)
@@ -152,3 +152,47 @@ BOOST_AUTO_TEST_CASE (import_dcp_markers_test)
        BOOST_REQUIRE(markers.find(dcp::LFMC) != markers.end());
        BOOST_CHECK(markers[dcp::LFMC] == dcpomatic::ContentTime(960000));
 }
+
+
+/** Check that DCP metadata (ratings and content version) are imported correctly */
+BOOST_AUTO_TEST_CASE (import_dcp_metadata_test)
+{
+       /* Make a DCP with some ratings and a content version */
+       shared_ptr<Film> film = new_test_film2 ("import_dcp_metadata_test");
+       shared_ptr<Content> content = content_factory("test/data/flat_red.png").front();
+       film->examine_and_add_content (content);
+       BOOST_REQUIRE (!wait_for_jobs());
+
+       content->video->set_length (10);
+
+       std::vector<dcp::Rating> ratings;
+       ratings.push_back (dcp::Rating("BBFC", "15"));
+       ratings.push_back (dcp::Rating("MPAA", "NC-17"));
+       film->set_ratings (ratings);
+
+       film->set_content_version ("Fred");
+
+       film->make_dcp ();
+       BOOST_REQUIRE (!wait_for_jobs());
+
+       /* Import the DCP to a new film and check the metadata */
+       shared_ptr<Film> film2 = new_test_film2 ("import_dcp_metadata_test2");
+       shared_ptr<DCPContent> imported (new DCPContent(film->dir(film->dcp_name())));
+       film2->examine_and_add_content (imported);
+       BOOST_REQUIRE (!wait_for_jobs());
+       film2->write_metadata ();
+
+       BOOST_CHECK (imported->ratings() == ratings);
+       BOOST_CHECK_EQUAL (imported->content_version(), "Fred");
+
+       /* Load that film and check that the metadata has been loaded */
+       shared_ptr<Film> film3(new Film(boost::filesystem::path("build/test/import_dcp_metadata_test2")));
+       film3->read_metadata ();
+       BOOST_REQUIRE (film3->content().size() == 1);
+       shared_ptr<DCPContent> reloaded = dynamic_pointer_cast<DCPContent>(film3->content().front());
+       BOOST_REQUIRE (reloaded);
+
+       BOOST_CHECK (reloaded->ratings() == ratings);
+       BOOST_CHECK_EQUAL (reloaded->content_version(), "Fred");
+}
+