diff options
| author | Carl Hetherington <cth@carlh.net> | 2025-03-26 23:59:30 +0100 |
|---|---|---|
| committer | Carl Hetherington <cth@carlh.net> | 2025-03-27 01:42:04 +0100 |
| commit | 2ef30cbe66ca819588bf43d892223ed9864c0e9a (patch) | |
| tree | 6528f5abdbb2f3bcf8d764b0e049af5006030f59 | |
| parent | 045a37dc877aecf907a517b0ec62a79efbf63f89 (diff) | |
Introduce and use dcp::Profile.v1.10.18
This replaces the specific flags passed to DCP::write(), is a property
of the CPL (where it seems to belong) and allows us to write what I hear
is the correct metadata for this mythical Bv2.0 that somebody invented.
| -rw-r--r-- | src/cpl.cc | 24 | ||||
| -rw-r--r-- | src/cpl.h | 23 | ||||
| -rw-r--r-- | src/dcp.cc | 3 | ||||
| -rw-r--r-- | src/dcp.h | 2 | ||||
| -rw-r--r-- | src/profile.h | 47 | ||||
| -rw-r--r-- | src/verify.cc | 8 | ||||
| -rw-r--r-- | src/wscript | 1 | ||||
| -rw-r--r-- | test/cpl_metadata_test.cc | 4 | ||||
| -rw-r--r-- | test/mono_mpeg2_picture_read_test.cc | 2 | ||||
| -rw-r--r-- | test/ref/cpl_metadata_test1.xml | 2 | ||||
| -rw-r--r-- | test/ref/cpl_metadata_test2.xml | 2 | ||||
| -rw-r--r-- | test/ref/cpl_metadata_test3.xml | 2 | ||||
| -rw-r--r-- | test/ref/cpl_metadata_test4.xml | 2 | ||||
| -rw-r--r-- | test/ref/cpl_metadata_test5.xml | 2 |
14 files changed, 92 insertions, 32 deletions
@@ -89,7 +89,7 @@ static string const smpte_395_ns = "http://www.smpte-ra.org/reg/395/2014/13/1/aa static string const smpte_335_ns = "http://www.smpte-ra.org/reg/335/2012"; -CPL::CPL(string annotation_text, ContentKind content_kind, Standard standard) +CPL::CPL(string annotation_text, ContentKind content_kind, Standard standard, Profile profile) /* default _content_title_text to annotation_text */ : _issuer("libdcp", dcp::version) , _creator("libdcp", dcp::version) @@ -98,6 +98,7 @@ CPL::CPL(string annotation_text, ContentKind content_kind, Standard standard) , _content_title_text(annotation_text) , _content_kind(content_kind) , _standard(standard) + , _profile(profile) { ContentVersion cv; cv.label_text = cv.id + LocalTime().as_string(); @@ -178,6 +179,8 @@ CPL::CPL(boost::filesystem::path file, vector<dcp::VerificationNote>* notes) if (metadata) { read_composition_metadata_asset(metadata, notes); _read_composition_metadata = true; + } else { + _profile = Profile::SMPTE_A; } } @@ -204,7 +207,7 @@ CPL::set(std::vector<std::shared_ptr<Reel>> reels) void -CPL::write_xml(boost::filesystem::path file, shared_ptr<const CertificateChain> signer, bool include_mca_subdescriptors) const +CPL::write_xml(boost::filesystem::path file, shared_ptr<const CertificateChain> signer) const { xmlpp::Document doc; xmlpp::Element* root; @@ -248,8 +251,8 @@ CPL::write_xml(boost::filesystem::path file, shared_ptr<const CertificateChain> bool first = true; for (auto i: _reels) { auto asset_list = i->write_to_cpl(reel_list, _standard); - if (first && _standard == Standard::SMPTE) { - maybe_write_composition_metadata_asset(asset_list, include_mca_subdescriptors); + if (first && _standard == Standard::SMPTE && _profile != Profile::SMPTE_A) { + maybe_write_composition_metadata_asset(asset_list); first = false; } } @@ -395,6 +398,12 @@ CPL::read_composition_metadata_asset(cxml::ConstNodePtr node, vector<dcp::Verifi _sign_language_video_language = extension_metadata("http://isdcf.com/2017/10/SignLanguageVideo", "Sign Language Video", "Language Tag"); _dolby_edr_image_transfer_function = extension_metadata("http://www.dolby.com/schemas/2014/EDR-Metadata", "Dolby EDR", "image transfer function"); + + if (node->optional_node_child("MCASubDescriptors")) { + _profile = Profile::SMPTE_BV21; + } else { + _profile = Profile::SMPTE_BV20; + } } @@ -474,7 +483,7 @@ CPL::write_mca_subdescriptors(xmlpp::Element* parent, shared_ptr<const SoundAsse * is missing this method will do nothing. */ void -CPL::maybe_write_composition_metadata_asset(xmlpp::Element* node, bool include_mca_subdescriptors) const +CPL::maybe_write_composition_metadata_asset(xmlpp::Element* node) const { if ( !_main_sound_configuration || @@ -586,8 +595,9 @@ CPL::maybe_write_composition_metadata_asset(xmlpp::Element* node, bool include_m cxml::add_child(property, "Value", string("meta"))->add_child_text(property_value); }; + string const profile_name = _profile == Profile::SMPTE_BV20 ? "2.0" : "2.1"; /* SMPTE Bv2.1 8.6.3 */ - add_extension_metadata("http://isdcf.com/ns/cplmd/app", "Application", "DCP Constraints Profile", "SMPTE-RDD-52:2020-Bv2.1"); + add_extension_metadata("http://isdcf.com/ns/cplmd/app", "Application", "DCP Constraints Profile", fmt::format("SMPTE-RDD-52:2020-Bv{}", profile_name)); if (_sign_language_video_language) { add_extension_metadata("http://isdcf.com/2017/10/SignLanguageVideo", "Sign Language Video", "Language Tag", *_sign_language_video_language); @@ -599,7 +609,7 @@ CPL::maybe_write_composition_metadata_asset(xmlpp::Element* node, bool include_m if (_reels.front()->main_sound()) { auto asset = _reels.front()->main_sound()->asset(); - if (asset && include_mca_subdescriptors) { + if (asset && _profile == Profile::SMPTE_BV21) { write_mca_subdescriptors(meta, asset); } } @@ -47,6 +47,7 @@ #include "key.h" #include "language_tag.h" #include "main_sound_configuration.h" +#include "profile.h" #include "rating.h" #include "verify.h" #include <boost/filesystem.hpp> @@ -82,7 +83,7 @@ class SoundAsset; class CPL : public Asset { public: - CPL(std::string annotation_text, ContentKind content_kind, Standard standard); + CPL(std::string annotation_text, ContentKind content_kind, Standard standard, Profile profile = Profile::SMPTE_BV21); /** Construct a CPL object from a XML file. * If notes is not null, non-fatal errors will be added. @@ -128,14 +129,8 @@ public: * * @param file Filename to write * @param signer Signer to sign the CPL, or 0 to add no signature - * @param include_mca_subdescriptors true to add a MCASubDescriptors tag to metadata, - * false to omit it. */ - void write_xml( - boost::filesystem::path file, - std::shared_ptr<const CertificateChain>, - bool include_mca_subdescriptors = true - ) const; + void write_xml(boost::filesystem::path file, std::shared_ptr<const CertificateChain>) const; void resolve_refs(std::vector<std::shared_ptr<Asset>>); @@ -343,6 +338,10 @@ public: return _standard; } + Profile profile() const { + return _profile; + } + /** @return true iff this CPL was read from a file and it contained * a CompositionMetadataAsset node. */ @@ -359,7 +358,7 @@ protected: private: friend struct ::verify_invalid_language3; - void maybe_write_composition_metadata_asset(xmlpp::Element* node, bool include_mca_subdescriptors) const; + void maybe_write_composition_metadata_asset(xmlpp::Element* node) const; void read_composition_metadata_asset(cxml::ConstNodePtr node, std::vector<dcp::VerificationNote>* notes); void write_mca_subdescriptors(xmlpp::Element* parent, std::shared_ptr<const SoundAsset> asset) const; @@ -403,6 +402,12 @@ private: /** Standard of CPL that was read in */ Standard _standard; + /** SMPTE "profile" for this CPL (only applicable if _standard == Standard::SMPTE) + * One of the CPL constructors sets this, and one guesses it from the contents of the + * CPL. The guess may be wrong (since it is only based on the presence of the + * CompositionMetadataAsset and the MCASubDescriptors within). + */ + Profile _profile = Profile::SMPTE_BV21; }; @@ -451,7 +451,6 @@ DCP::write_volindex (Standard standard) const void DCP::write_xml( shared_ptr<const CertificateChain> signer, - bool include_mca_subdescriptors, NameFormat name_format, optional<string> group_id ) @@ -473,7 +472,7 @@ DCP::write_xml( for (auto i: cpls()) { NameFormat::Map values; values['t'] = "cpl"; - i->write_xml(_directory / (name_format.get(values, "_" + i->id() + ".xml")), signer, include_mca_subdescriptors); + i->write_xml(_directory / (name_format.get(values, "_" + i->id() + ".xml")), signer); } if (_pkls.empty()) { @@ -151,12 +151,10 @@ public: /** Write all the XML files for this DCP. * @param signer Signer to use - * @param include_mca_subdescriptors true to write MCA subdescriptors to CPLs. * @param name_format Name format to use for the CPL and PKL filenames */ void write_xml( std::shared_ptr<const CertificateChain> signer = std::shared_ptr<const CertificateChain>(), - bool include_mca_subdescriptors = true, NameFormat name_format = NameFormat("%t"), boost::optional<std::string> group_id = boost::none ); diff --git a/src/profile.h b/src/profile.h new file mode 100644 index 00000000..41d8ef1a --- /dev/null +++ b/src/profile.h @@ -0,0 +1,47 @@ +/* + Copyright (C) 2025 Carl Hetherington <cth@carlh.net> + + This file is part of libdcp. + + libdcp 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. + + libdcp 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 libdcp. If not, see <http://www.gnu.org/licenses/>. + + In addition, as a special exception, the copyright holders give + permission to link the code of portions of this program with the + OpenSSL library under certain conditions as described in each + individual source file, and distribute linked combinations + including the two. + + You must obey the GNU General Public License in all respects + for all of the code used other than OpenSSL. If you modify + file(s) with this exception, you may extend this exception to your + version of the file(s), but you are not obligated to do so. If you + do not wish to do so, delete this exception statement from your + version. If you delete this exception statement from all source + files in the program, then also delete it here. +*/ + + +namespace dcp { + + +enum class Profile +{ + SMPTE_A, + SMPTE_BV20, + SMPTE_BV21 +}; + + +} + diff --git a/src/verify.cc b/src/verify.cc index 7a2fd5cd..4568aaa1 100644 --- a/src/verify.cc +++ b/src/verify.cc @@ -1319,12 +1319,14 @@ dcp::verify_extension_metadata(Context& context) } if (auto property_list = extension->optional_node_child("PropertyList")) { auto properties = property_list->node_children("Property"); - auto is_bv21 = [](shared_ptr<const cxml::Node> property) { + auto is_bv_20_or_21 = [](shared_ptr<const cxml::Node> property) { auto name = property->optional_node_child("Name"); auto value = property->optional_node_child("Value"); - return name && value && name->content() == "DCP Constraints Profile" && value->content() == "SMPTE-RDD-52:2020-Bv2.1"; + string content = value ? value->content() : ""; + return name && value && name->content() == "DCP Constraints Profile" && + (content == "SMPTE-RDD-52:2020-Bv2.0" || content == "SMPTE-RDD-52:2020-Bv2.1"); }; - if (!std::any_of(properties.begin(), properties.end(), is_bv21)) { + if (!std::any_of(properties.begin(), properties.end(), is_bv_20_or_21)) { malformed = "No correctly-formed DCP Constraints Profile found"; } } diff --git a/src/wscript b/src/wscript index d3d615be..1ef4f4ca 100644 --- a/src/wscript +++ b/src/wscript @@ -208,6 +208,7 @@ def build(bld): picture_asset.h piecewise_lut.h pkl.h + profile.h rating.h raw_convert.h reel.h diff --git a/test/cpl_metadata_test.cc b/test/cpl_metadata_test.cc index f3e44f46..2dc6da7d 100644 --- a/test/cpl_metadata_test.cc +++ b/test/cpl_metadata_test.cc @@ -299,7 +299,7 @@ BOOST_AUTO_TEST_CASE (cpl_metadata_write_test1) { RNGFixer fix; - dcp::CPL cpl("", dcp::ContentKind::FEATURE, dcp::Standard::SMPTE); + dcp::CPL cpl("", dcp::ContentKind::FEATURE, dcp::Standard::SMPTE, dcp::Profile::SMPTE_BV20); cpl.set_issue_date ("2020-08-28T13:35:06+02:00"); vector<dcp::ContentVersion> cv = { @@ -385,7 +385,7 @@ BOOST_AUTO_TEST_CASE (cpl_metadata_write_test2) { RNGFixer fix; - dcp::CPL cpl("", dcp::ContentKind::FEATURE, dcp::Standard::SMPTE); + dcp::CPL cpl("", dcp::ContentKind::FEATURE, dcp::Standard::SMPTE, dcp::Profile::SMPTE_BV20); cpl.set_issue_date ("2020-08-28T13:35:06+02:00"); cpl.set_content_version (dcp::ContentVersion("id", "version")); cpl.set_issuer ("libdcp1.6.4devel"); diff --git a/test/mono_mpeg2_picture_read_test.cc b/test/mono_mpeg2_picture_read_test.cc index f0d4aac0..df7a5aec 100644 --- a/test/mono_mpeg2_picture_read_test.cc +++ b/test/mono_mpeg2_picture_read_test.cc @@ -45,8 +45,6 @@ extern "C" { BOOST_AUTO_TEST_CASE(mpeg_mono_picture_read_test) { dcp::MonoMPEG2PictureAsset asset(private_test / "data" / "mas" / "r2.mxf" ); - std::cout << "frame rate " << asset.frame_rate().numerator << "\n"; - std::cout << "duration " << asset.intrinsic_duration() << "\n"; auto reader = asset.start_read(); diff --git a/test/ref/cpl_metadata_test1.xml b/test/ref/cpl_metadata_test1.xml index 1140c07d..86859c7b 100644 --- a/test/ref/cpl_metadata_test1.xml +++ b/test/ref/cpl_metadata_test1.xml @@ -71,7 +71,7 @@ <meta:PropertyList> <meta:Property> <meta:Name>DCP Constraints Profile</meta:Name> - <meta:Value>SMPTE-RDD-52:2020-Bv2.1</meta:Value> + <meta:Value>SMPTE-RDD-52:2020-Bv2.0</meta:Value> </meta:Property> </meta:PropertyList> </meta:ExtensionMetadata> diff --git a/test/ref/cpl_metadata_test2.xml b/test/ref/cpl_metadata_test2.xml index d04d25af..79731518 100644 --- a/test/ref/cpl_metadata_test2.xml +++ b/test/ref/cpl_metadata_test2.xml @@ -47,7 +47,7 @@ <meta:PropertyList> <meta:Property> <meta:Name>DCP Constraints Profile</meta:Name> - <meta:Value>SMPTE-RDD-52:2020-Bv2.1</meta:Value> + <meta:Value>SMPTE-RDD-52:2020-Bv2.0</meta:Value> </meta:Property> </meta:PropertyList> </meta:ExtensionMetadata> diff --git a/test/ref/cpl_metadata_test3.xml b/test/ref/cpl_metadata_test3.xml index 38d732a6..265483fe 100644 --- a/test/ref/cpl_metadata_test3.xml +++ b/test/ref/cpl_metadata_test3.xml @@ -46,7 +46,7 @@ <meta:PropertyList> <meta:Property> <meta:Name>DCP Constraints Profile</meta:Name> - <meta:Value>SMPTE-RDD-52:2020-Bv2.1</meta:Value> + <meta:Value>SMPTE-RDD-52:2020-Bv2.0</meta:Value> </meta:Property> </meta:PropertyList> </meta:ExtensionMetadata> diff --git a/test/ref/cpl_metadata_test4.xml b/test/ref/cpl_metadata_test4.xml index e4459375..b4984ccc 100644 --- a/test/ref/cpl_metadata_test4.xml +++ b/test/ref/cpl_metadata_test4.xml @@ -47,7 +47,7 @@ <meta:PropertyList> <meta:Property> <meta:Name>DCP Constraints Profile</meta:Name> - <meta:Value>SMPTE-RDD-52:2020-Bv2.1</meta:Value> + <meta:Value>SMPTE-RDD-52:2020-Bv2.0</meta:Value> </meta:Property> </meta:PropertyList> </meta:ExtensionMetadata> diff --git a/test/ref/cpl_metadata_test5.xml b/test/ref/cpl_metadata_test5.xml index 55209e53..02757e21 100644 --- a/test/ref/cpl_metadata_test5.xml +++ b/test/ref/cpl_metadata_test5.xml @@ -47,7 +47,7 @@ <meta:PropertyList> <meta:Property> <meta:Name>DCP Constraints Profile</meta:Name> - <meta:Value>SMPTE-RDD-52:2020-Bv2.1</meta:Value> + <meta:Value>SMPTE-RDD-52:2020-Bv2.0</meta:Value> </meta:Property> </meta:PropertyList> </meta:ExtensionMetadata> |
