diff options
| author | Carl Hetherington <cth@carlh.net> | 2022-12-11 22:27:34 +0100 |
|---|---|---|
| committer | Carl Hetherington <cth@carlh.net> | 2023-02-18 00:35:01 +0100 |
| commit | 214c3093f7e985cde610457fae9e1f97068efde5 (patch) | |
| tree | 7f8d919ec8e6b6bf6dafdbe141e1c34e65914d16 | |
| parent | b94821d7953dae7d9e58f703e66dca59e9086216 (diff) | |
and default to writing the 2014 namespace.
| -rw-r--r-- | src/interop_subtitle_asset.h | 5 | ||||
| -rw-r--r-- | src/smpte_subtitle_asset.cc | 40 | ||||
| -rw-r--r-- | src/smpte_subtitle_asset.h | 18 | ||||
| -rw-r--r-- | src/subtitle_asset.h | 3 | ||||
| -rw-r--r-- | src/subtitle_standard.cc | 57 | ||||
| -rw-r--r-- | src/subtitle_standard.h | 57 | ||||
| -rw-r--r-- | src/wscript | 2 | ||||
| -rw-r--r-- | test/data/2007.mxf | bin | 0 -> 17297 bytes | |||
| -rw-r--r-- | test/data/2010.mxf | bin | 0 -> 17297 bytes | |||
| -rw-r--r-- | test/data/2014.mxf | bin | 0 -> 17297 bytes | |||
| -rw-r--r-- | test/smpte_subtitle_test.cc | 40 |
11 files changed, 214 insertions, 8 deletions
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 <boost/filesystem.hpp> @@ -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<cxml::Document> 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<dcp::SMPTELoadFontNode> (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<Subtitle> 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 <boost/filesystem.hpp> @@ -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<cxml::Document> xml); void read_mxf_descriptor (std::shared_ptr<ASDCP::TimedText::MXFReader> reader); void read_mxf_resources (std::shared_ptr<ASDCP::TimedText::MXFReader> reader, std::shared_ptr<DecryptionContext> 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<Time> _start_time; + /** There are two SMPTE standards describing subtitles, 428-7:2010 and 428-7:2014, and they + * have different interpretations of what Vposition means. Though libdcp does not need to + * know the difference, this variable stores the standard from the namespace that this asset was + * written with (or will be written with). + */ + SubtitleStandard _subtitle_standard; std::vector<std::shared_ptr<SMPTELoadFontNode>> _load_font_nodes; /** UUID for the XML inside the MXF, which should be the same as the ResourceID in the MXF (our _resource_id) diff --git a/src/subtitle_asset.h b/src/subtitle_asset.h index 7448ac9a..012050b1 100644 --- a/src/subtitle_asset.h +++ b/src/subtitle_asset.h @@ -44,6 +44,7 @@ #include "array_data.h" #include "asset.h" #include "dcp_time.h" +#include "subtitle_standard.h" #include "subtitle_string.h" #include <libcxml/cxml.h> #include <boost/shared_array.hpp> @@ -132,6 +133,8 @@ public: return _raw_xml; } + virtual SubtitleStandard subtitle_standard() const = 0; + static std::string format_xml (xmlpp::Document const& document, std::vector<std::pair<std::string, std::string>> const& namespaces); protected: diff --git a/src/subtitle_standard.cc b/src/subtitle_standard.cc new file mode 100644 index 00000000..101f84d4 --- /dev/null +++ b/src/subtitle_standard.cc @@ -0,0 +1,57 @@ +/* + Copyright (C) 2012-2021 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. +*/ + + +#include "subtitle_standard.h" + + +using namespace dcp; + + +bool +dcp::uses_baseline(SubtitleStandard standard) +{ + return standard == SubtitleStandard::INTEROP || standard == SubtitleStandard::SMPTE_2014; +} + + +bool +dcp::uses_bounding_box(SubtitleStandard standard) +{ + /* I didn't check the 2007 version but I am assuming they didn't start out using Interop-style + * then change their mind to bounding-box and then change it back again. + */ + return standard == SubtitleStandard::SMPTE_2007 || standard == SubtitleStandard::SMPTE_2010; +} + + diff --git a/src/subtitle_standard.h b/src/subtitle_standard.h new file mode 100644 index 00000000..95972e20 --- /dev/null +++ b/src/subtitle_standard.h @@ -0,0 +1,57 @@ +/* + Copyright (C) 2012-2021 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. +*/ + + +#ifndef LIBDCP_SUBTITLE_STANDARD_H +#define LIBDCP_SUBTITLE_STANDARD_H + + +namespace dcp { + + +enum class SubtitleStandard { + INTEROP, + SMPTE_2007, + SMPTE_2010, + SMPTE_2014 +}; + + +bool uses_baseline(SubtitleStandard standard); +bool uses_bounding_box(SubtitleStandard standard); + + +} + +#endif + diff --git a/src/wscript b/src/wscript index 39e3351d..d16e15fc 100644 --- a/src/wscript +++ b/src/wscript @@ -113,6 +113,7 @@ def build(bld): subtitle_asset.cc subtitle_asset_internal.cc subtitle_image.cc + subtitle_standard.cc subtitle_string.cc transfer_function.cc types.cc @@ -213,6 +214,7 @@ def build(bld): subtitle.h subtitle_asset.h subtitle_image.h + subtitle_standard.h subtitle_string.h transfer_function.h types.h diff --git a/test/data/2007.mxf b/test/data/2007.mxf Binary files differnew file mode 100644 index 00000000..3cdf4861 --- /dev/null +++ b/test/data/2007.mxf diff --git a/test/data/2010.mxf b/test/data/2010.mxf Binary files differnew file mode 100644 index 00000000..1d1b8554 --- /dev/null +++ b/test/data/2010.mxf diff --git a/test/data/2014.mxf b/test/data/2014.mxf Binary files differnew file mode 100644 index 00000000..63622640 --- /dev/null +++ b/test/data/2014.mxf diff --git a/test/smpte_subtitle_test.cc b/test/smpte_subtitle_test.cc index f8412daa..a23a7c45 100644 --- a/test/smpte_subtitle_test.cc +++ b/test/smpte_subtitle_test.cc @@ -708,3 +708,43 @@ BOOST_AUTO_TEST_CASE (write_subtitles_in_vertical_order_with_bottom_alignment) ); } + +BOOST_AUTO_TEST_CASE(smpte_subtitle_standard_written_correctly) +{ + RNGFixer fixer; + + boost::filesystem::path const ref = "test/data"; + boost::filesystem::path const out = "build/test/smpte_subtitle_standard_written_correctly"; + + boost::filesystem::remove_all(out); + boost::filesystem::create_directories(out); + + dcp::SMPTESubtitleAsset test_2014; + test_2014.set_issue_date(dcp::LocalTime("2020-01-01T14:00:00")); + test_2014.write(out / "2014.mxf"); + check_file(ref / "2014.mxf", out / "2014.mxf"); + + dcp::SMPTESubtitleAsset test_2010(dcp::SubtitleStandard::SMPTE_2010); + test_2010.set_issue_date(dcp::LocalTime("2020-01-01T14:00:00")); + test_2010.write(out / "2010.mxf"); + check_file(ref / "2010.mxf", out / "2010.mxf"); + + dcp::SMPTESubtitleAsset test_2007(dcp::SubtitleStandard::SMPTE_2007); + test_2007.set_issue_date(dcp::LocalTime("2020-01-01T14:00:00")); + test_2007.write(out / "2007.mxf"); + check_file(ref / "2007.mxf", out / "2007.mxf"); +} + + +BOOST_AUTO_TEST_CASE(smpte_subtitle_standard_read_correctly) +{ + dcp::SMPTESubtitleAsset test_2007("test/data/2007.mxf"); + BOOST_CHECK(test_2007.subtitle_standard() == dcp::SubtitleStandard::SMPTE_2007); + + dcp::SMPTESubtitleAsset test_2010("test/data/2010.mxf"); + BOOST_CHECK(test_2010.subtitle_standard() == dcp::SubtitleStandard::SMPTE_2010); + + dcp::SMPTESubtitleAsset test_2014("test/data/2014.mxf"); + BOOST_CHECK(test_2014.subtitle_standard() == dcp::SubtitleStandard::SMPTE_2014); +} + |
