summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorCarl Hetherington <cth@carlh.net>2024-04-18 11:51:03 +0200
committerCarl Hetherington <cth@carlh.net>2024-04-18 11:51:03 +0200
commit816365d20e0c6ef37b6bf499a42a0d3ecad22c05 (patch)
treee3ffd2029657ef0b316f729579077baf051f50a5 /src
parent3ab56573dbfb395fea493096182dc14c09fb961f (diff)
parent869462070671b273ac528e075ac1c00a417cc8a0 (diff)
Merge remote-tracking branch 'origin/main' into v1.9.x
Diffstat (limited to 'src')
-rw-r--r--src/cpl.cc56
-rw-r--r--src/cpl.h17
-rw-r--r--src/dcp.cc2
-rw-r--r--src/verify.cc4
-rw-r--r--src/verify.h9
5 files changed, 74 insertions, 14 deletions
diff --git a/src/cpl.cc b/src/cpl.cc
index 6a9a46b5..e8cec95c 100644
--- a/src/cpl.cc
+++ b/src/cpl.cc
@@ -104,7 +104,7 @@ CPL::CPL (string annotation_text, ContentKind content_kind, Standard standard)
}
-CPL::CPL (boost::filesystem::path file)
+CPL::CPL (boost::filesystem::path file, vector<dcp::VerificationNote>* notes)
: Asset (file)
, _content_kind (ContentKind::FEATURE)
{
@@ -116,7 +116,17 @@ CPL::CPL (boost::filesystem::path file)
} else if (f.namespace_uri() == cpl_smpte_ns) {
_standard = Standard::SMPTE;
} else {
- boost::throw_exception (XMLError ("Unrecognised CPL namespace " + f.namespace_uri()));
+ if (notes) {
+ notes->push_back(
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::ERROR,
+ dcp::VerificationNote::Code::INVALID_CPL_NAMESPACE,
+ f.namespace_uri(),
+ file
+ )
+ );
+ }
+ _standard = Standard::INTEROP;
}
_id = remove_urn_uuid (f.string_child ("Id"));
@@ -139,7 +149,16 @@ CPL::CPL (boost::filesystem::path file)
content_version->done ();
} else if (_standard == Standard::SMPTE) {
/* ContentVersion is required in SMPTE */
- throw XMLError ("Missing ContentVersion tag in CPL");
+ if (notes) {
+ notes->push_back(
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::ERROR,
+ dcp::VerificationNote::Code::MISSING_CPL_CONTENT_VERSION,
+ _id,
+ file
+ )
+ );
+ }
}
auto rating_list = f.node_child ("RatingList");
for (auto i: rating_list->node_children("Rating")) {
@@ -345,21 +364,32 @@ CPL::read_composition_metadata_asset (cxml::ConstNodePtr node)
}
auto eml = node->optional_node_child ("ExtensionMetadataList");
- if (eml) {
+
+ auto extension_metadata = [eml](string scope, string name, string property) -> boost::optional<std::string> {
+ if (!eml) {
+ return {};
+ }
+
for (auto i: eml->node_children("ExtensionMetadata")) {
- auto name = i->optional_string_child("Name");
- if (name && *name == "Sign Language Video") {
+ auto xml_scope = i->optional_string_attribute("scope");
+ auto xml_name = i->optional_string_child("Name");
+ if (xml_scope && *xml_scope == scope && xml_name && *xml_name == name) {
auto property_list = i->node_child("PropertyList");
for (auto j: property_list->node_children("Property")) {
- auto name = j->optional_string_child("Name");
- auto value = j->optional_string_child("Value");
- if (name && value && *name == "Language Tag") {
- _sign_language_video_language = *value;
+ auto property_name = j->optional_string_child("Name");
+ auto property_value = j->optional_string_child("Value");
+ if (property_name && property_value && *property_name == property) {
+ return property_value;
}
}
}
}
- }
+
+ return {};
+ };
+
+ _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");
}
@@ -558,6 +588,10 @@ CPL::maybe_write_composition_metadata_asset(xmlpp::Element* node, bool include_m
add_extension_metadata ("http://isdcf.com/2017/10/SignLanguageVideo", "Sign Language Video", "Language Tag", *_sign_language_video_language);
}
+ if (_dolby_edr_image_transfer_function) {
+ add_extension_metadata("http://www.dolby.com/schemas/2014/EDR-Metadata", "Dolby EDR", "image transfer function", *_dolby_edr_image_transfer_function);
+ }
+
if (_reels.front()->main_sound()) {
auto asset = _reels.front()->main_sound()->asset();
if (asset && include_mca_subdescriptors) {
diff --git a/src/cpl.h b/src/cpl.h
index 25c294eb..824faaa1 100644
--- a/src/cpl.h
+++ b/src/cpl.h
@@ -47,6 +47,7 @@
#include "key.h"
#include "language_tag.h"
#include "rating.h"
+#include "verify.h"
#include <boost/filesystem.hpp>
#include <boost/function.hpp>
#include <boost/optional.hpp>
@@ -82,8 +83,11 @@ class CPL : public Asset
public:
CPL (std::string annotation_text, ContentKind content_kind, Standard standard);
- /** Construct a CPL object from a XML file */
- explicit CPL (boost::filesystem::path file);
+ /** Construct a CPL object from a XML file.
+ * If notes is not null, non-fatal errors will be added.
+ * Exceptions will be thrown on non-recoverable errors.
+ */
+ explicit CPL(boost::filesystem::path file, std::vector<dcp::VerificationNote>* notes = nullptr);
bool equals (
std::shared_ptr<const Asset> other,
@@ -326,6 +330,14 @@ public:
return _sign_language_video_language;
}
+ void set_dolby_edr_image_transfer_function(std::string function) {
+ _dolby_edr_image_transfer_function = function;
+ }
+
+ boost::optional<std::string> dolby_edr_image_transfer_function() const {
+ return _dolby_edr_image_transfer_function;
+ }
+
Standard standard () const {
return _standard;
}
@@ -383,6 +395,7 @@ private:
/* See note for _release_territory above */
std::vector<std::string> _additional_subtitle_languages;
boost::optional<std::string> _sign_language_video_language;
+ boost::optional<std::string> _dolby_edr_image_transfer_function;
bool _read_composition_metadata = false;
std::vector<std::shared_ptr<Reel>> _reels;
diff --git a/src/dcp.cc b/src/dcp.cc
index 2906d575..7b238b97 100644
--- a/src/dcp.cc
+++ b/src/dcp.cc
@@ -234,7 +234,7 @@ DCP::read (vector<dcp::VerificationNote>* notes, bool ignore_incorrect_picture_m
delete p;
if (root == "CompositionPlaylist") {
- auto cpl = make_shared<CPL>(path);
+ auto cpl = make_shared<CPL>(path, notes);
if (cpl->standard() != standard && notes) {
notes->push_back ({VerificationNote::Type::ERROR, VerificationNote::Code::MISMATCHED_STANDARD});
}
diff --git a/src/verify.cc b/src/verify.cc
index a61c3a92..cfcce04f 100644
--- a/src/verify.cc
+++ b/src/verify.cc
@@ -2203,6 +2203,10 @@ dcp::note_to_string(VerificationNote note, function<string (string)> process_str
return compose("The <LabelText> in a <ContentVersion> in CPL %1 is empty", note.cpl_id().get());
case VerificationNote::Code::VALID_CONTENT_VERSION_LABEL_TEXT:
return compose("CPL has valid <ContentVersion> %1", note.note().get());
+ case VerificationNote::Code::INVALID_CPL_NAMESPACE:
+ return compose("The namespace %1 in CPL %2 is invalid", note.note().get(), note.cpl_id().get());
+ case VerificationNote::Code::MISSING_CPL_CONTENT_VERSION:
+ return compose("The CPL %1 has no <ContentVersion> tag", note.cpl_id().get());
}
return "";
diff --git a/src/verify.h b/src/verify.h
index 77b65760..b9e3623f 100644
--- a/src/verify.h
+++ b/src/verify.h
@@ -492,6 +492,15 @@ public:
*/
EMPTY_CONTENT_VERSION_LABEL_TEXT,
VALID_CONTENT_VERSION_LABEL_TEXT,
+ /** The CPL namespace is not valid.
+ * note contains the invalid namespace
+ * file contains the CPL filename
+ */
+ INVALID_CPL_NAMESPACE,
+ /** A SMPTE CPL does not contain a _<ContentVersion>_ tag
+ * file contains the CPL filename
+ */
+ MISSING_CPL_CONTENT_VERSION
};
VerificationNote (Type type, Code code)