summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarl Hetherington <cth@carlh.net>2025-03-26 23:59:30 +0100
committerCarl Hetherington <cth@carlh.net>2025-03-27 01:42:04 +0100
commit2ef30cbe66ca819588bf43d892223ed9864c0e9a (patch)
tree6528f5abdbb2f3bcf8d764b0e049af5006030f59
parent045a37dc877aecf907a517b0ec62a79efbf63f89 (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.cc24
-rw-r--r--src/cpl.h23
-rw-r--r--src/dcp.cc3
-rw-r--r--src/dcp.h2
-rw-r--r--src/profile.h47
-rw-r--r--src/verify.cc8
-rw-r--r--src/wscript1
-rw-r--r--test/cpl_metadata_test.cc4
-rw-r--r--test/mono_mpeg2_picture_read_test.cc2
-rw-r--r--test/ref/cpl_metadata_test1.xml2
-rw-r--r--test/ref/cpl_metadata_test2.xml2
-rw-r--r--test/ref/cpl_metadata_test3.xml2
-rw-r--r--test/ref/cpl_metadata_test4.xml2
-rw-r--r--test/ref/cpl_metadata_test5.xml2
14 files changed, 92 insertions, 32 deletions
diff --git a/src/cpl.cc b/src/cpl.cc
index 8576bae3..695192fe 100644
--- a/src/cpl.cc
+++ b/src/cpl.cc
@@ -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);
}
}
diff --git a/src/cpl.h b/src/cpl.h
index 389ec411..5fc56e25 100644
--- a/src/cpl.h
+++ b/src/cpl.h
@@ -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;
};
diff --git a/src/dcp.cc b/src/dcp.cc
index 795dfca7..06590407 100644
--- a/src/dcp.cc
+++ b/src/dcp.cc
@@ -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()) {
diff --git a/src/dcp.h b/src/dcp.h
index 5802ca2e..e1e2ce9c 100644
--- a/src/dcp.h
+++ b/src/dcp.h
@@ -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>