From 214c3093f7e985cde610457fae9e1f97068efde5 Mon Sep 17 00:00:00 2001 From: Carl Hetherington Date: Sun, 11 Dec 2022 22:27:34 +0100 Subject: Be explicit about the version of SMPTE 428-7 that is used for subtitles, and default to writing the 2014 namespace. --- src/interop_subtitle_asset.h | 5 ++++ src/smpte_subtitle_asset.cc | 40 ++++++++++++++++++++++++++---- src/smpte_subtitle_asset.h | 18 +++++++++++--- src/subtitle_asset.h | 3 +++ src/subtitle_standard.cc | 57 +++++++++++++++++++++++++++++++++++++++++++ src/subtitle_standard.h | 57 +++++++++++++++++++++++++++++++++++++++++++ src/wscript | 2 ++ test/data/2007.mxf | Bin 0 -> 17297 bytes test/data/2010.mxf | Bin 0 -> 17297 bytes test/data/2014.mxf | Bin 0 -> 17297 bytes test/smpte_subtitle_test.cc | 40 ++++++++++++++++++++++++++++++ 11 files changed, 214 insertions(+), 8 deletions(-) create mode 100644 src/subtitle_standard.cc create mode 100644 src/subtitle_standard.h create mode 100644 test/data/2007.mxf create mode 100644 test/data/2010.mxf create mode 100644 test/data/2014.mxf diff --git a/src/interop_subtitle_asset.h b/src/interop_subtitle_asset.h index 670dee27..23cf0b49 100644 --- a/src/interop_subtitle_asset.h +++ b/src/interop_subtitle_asset.h @@ -42,6 +42,7 @@ #include "subtitle_asset.h" +#include "subtitle_standard.h" #include @@ -126,6 +127,10 @@ public: return 1000; } + SubtitleStandard subtitle_standard() const override { + return SubtitleStandard::INTEROP; + } + static std::string static_pkl_type (Standard) { return "text/xml;asdcpKind=Subtitle"; } diff --git a/src/smpte_subtitle_asset.cc b/src/smpte_subtitle_asset.cc index 375bae0a..4b2ae8cd 100644 --- a/src/smpte_subtitle_asset.cc +++ b/src/smpte_subtitle_asset.cc @@ -72,13 +72,16 @@ using boost::starts_with; using namespace dcp; -static string const subtitle_smpte_ns = "http://www.smpte-ra.org/schemas/428-7/2010/DCST"; +static string const subtitle_smpte_ns_2007 = "http://www.smpte-ra.org/schemas/428-7/2007/DCST"; +static string const subtitle_smpte_ns_2010 = "http://www.smpte-ra.org/schemas/428-7/2010/DCST"; +static string const subtitle_smpte_ns_2014 = "http://www.smpte-ra.org/schemas/428-7/2014/DCST"; -SMPTESubtitleAsset::SMPTESubtitleAsset () - : MXF (Standard::SMPTE) +SMPTESubtitleAsset::SMPTESubtitleAsset(SubtitleStandard standard) + : MXF(Standard::SMPTE) , _edit_rate (24, 1) , _time_code_rate (24) + , _subtitle_standard(standard) , _xml_id (make_uuid()) { @@ -165,6 +168,15 @@ SMPTESubtitleAsset::SMPTESubtitleAsset (boost::filesystem::path file) void SMPTESubtitleAsset::parse_xml (shared_ptr xml) { + if (xml->namespace_uri() == subtitle_smpte_ns_2007) { + _subtitle_standard = SubtitleStandard::SMPTE_2007; + } else if (xml->namespace_uri() == subtitle_smpte_ns_2010) { + _subtitle_standard = SubtitleStandard::SMPTE_2010; + } else if (xml->namespace_uri() == subtitle_smpte_ns_2014) { + _subtitle_standard = SubtitleStandard::SMPTE_2014; + } else { + throw XMLError("Unrecognised subtitle namespace " + xml->namespace_uri()); + } _xml_id = remove_urn_uuid(xml->string_child("Id")); _load_font_nodes = type_children (xml, "LoadFont"); @@ -372,7 +384,7 @@ SMPTESubtitleAsset::xml_as_string () const subtitles_as_xml (root->add_child("SubtitleList"), _time_code_rate, Standard::SMPTE); - return format_xml(doc, { {"", subtitle_smpte_ns}, {"xs", "http://www.w3.org/2001/XMLSchema"} }); + return format_xml(doc, { {"", schema_namespace()}, {"xs", "http://www.w3.org/2001/XMLSchema"} }); } @@ -419,7 +431,7 @@ SMPTESubtitleAsset::write (boost::filesystem::path p) const } } - descriptor.NamespaceName = subtitle_smpte_ns; + descriptor.NamespaceName = schema_namespace(); unsigned int c; DCP_ASSERT (_xml_id); Kumu::hex2bin (_xml_id->c_str(), descriptor.AssetID, ASDCP::UUIDlen, &c); @@ -576,3 +588,21 @@ SMPTESubtitleAsset::add (shared_ptr s) _intrinsic_duration = latest_subtitle_out().as_editable_units_ceil(_edit_rate.numerator / _edit_rate.denominator); } + +string +SMPTESubtitleAsset::schema_namespace() const +{ + switch (_subtitle_standard) { + case SubtitleStandard::SMPTE_2007: + return subtitle_smpte_ns_2007; + case SubtitleStandard::SMPTE_2010: + return subtitle_smpte_ns_2010; + case SubtitleStandard::SMPTE_2014: + return subtitle_smpte_ns_2014; + default: + DCP_ASSERT(false); + } + + DCP_ASSERT(false); +} + diff --git a/src/smpte_subtitle_asset.h b/src/smpte_subtitle_asset.h index b707da12..2632e0a5 100644 --- a/src/smpte_subtitle_asset.h +++ b/src/smpte_subtitle_asset.h @@ -41,11 +41,12 @@ */ -#include "subtitle_asset.h" +#include "crypto_context.h" #include "language_tag.h" #include "local_time.h" #include "mxf.h" -#include "crypto_context.h" +#include "subtitle_asset.h" +#include "subtitle_standard.h" #include @@ -74,7 +75,7 @@ class SMPTELoadFontNode; class SMPTESubtitleAsset : public SubtitleAsset, public MXF { public: - SMPTESubtitleAsset (); + explicit SMPTESubtitleAsset(SubtitleStandard standard = SubtitleStandard::SMPTE_2014); /** Construct a SMPTESubtitleAsset by reading an MXF or XML file * @param file Filename @@ -190,6 +191,10 @@ public: return _resource_id; } + SubtitleStandard subtitle_standard() const override { + return _subtitle_standard; + } + static bool valid_mxf (boost::filesystem::path); static std::string static_pkl_type (Standard) { return "application/mxf"; @@ -213,6 +218,7 @@ private: void parse_xml (std::shared_ptr xml); void read_mxf_descriptor (std::shared_ptr reader); void read_mxf_resources (std::shared_ptr reader, std::shared_ptr dec); + std::string schema_namespace() const; /** The total length of this content in video frames. The amount of * content presented may be less than this. @@ -230,6 +236,12 @@ private: Fraction _edit_rate; int _time_code_rate = 0; boost::optional