summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorCarl Hetherington <cth@carlh.net>2016-05-24 23:02:38 +0100
committerCarl Hetherington <cth@carlh.net>2016-05-24 23:02:38 +0100
commitcb7c3db37d196b6e9ddad60937bd5314a95eadb2 (patch)
treeb686e05142b39208e4af8ab0a01e3b47c5256378 /src
parent096b175a661234d9e02a852cce9f56c4577b8259 (diff)
parent85c699d29aab7ca7f7218b3f7f859e10c9025e37 (diff)
Merge branch '1.0' of ssh://main.carlh.net/home/carl/git/libdcp into 1.0
Diffstat (limited to 'src')
-rw-r--r--src/colour_conversion.cc38
-rw-r--r--src/colour_conversion.h2
-rw-r--r--src/cpl.cc15
-rw-r--r--src/cpl.h7
-rw-r--r--src/dcp.cc43
-rw-r--r--src/dcp.h8
-rw-r--r--src/exceptions.cc6
-rw-r--r--src/exceptions.h6
-rw-r--r--src/modified_gamma_transfer_function.h7
9 files changed, 122 insertions, 10 deletions
diff --git a/src/colour_conversion.cc b/src/colour_conversion.cc
index 8c48c2e1..46bc717e 100644
--- a/src/colour_conversion.cc
+++ b/src/colour_conversion.cc
@@ -97,6 +97,44 @@ ColourConversion::p3_to_xyz ()
return *c;
}
+ColourConversion const &
+ColourConversion::rec1886_to_xyz ()
+{
+ /* According to Olivier on DCP-o-matic bug #832, Rec. 1886 is Rec. 709 with
+ 2.4 gamma, so here goes ...
+ */
+ static ColourConversion* c = new ColourConversion (
+ shared_ptr<const TransferFunction> (new GammaTransferFunction (2.4)),
+ YUV_TO_RGB_REC709,
+ Chromaticity (0.64, 0.33),
+ Chromaticity (0.3, 0.6),
+ Chromaticity (0.15, 0.06),
+ /* D65 */
+ Chromaticity (0.3127, 0.329),
+ optional<Chromaticity> (),
+ shared_ptr<const TransferFunction> (new GammaTransferFunction (2.6))
+ );
+ return *c;
+}
+
+ColourConversion const &
+ColourConversion::rec2020_to_xyz ()
+{
+ /* From Wikipedia */
+ static ColourConversion* c = new ColourConversion (
+ shared_ptr<const TransferFunction> (new ModifiedGammaTransferFunction (1 / 0.45, 0.08145, 0.0993, 4.5)),
+ YUV_TO_RGB_REC709,
+ Chromaticity (0.708, 0.292),
+ Chromaticity (0.170, 0.797),
+ Chromaticity (0.131, 0.046),
+ /* D65 */
+ Chromaticity (0.3127, 0.329),
+ optional<Chromaticity> (),
+ shared_ptr<const TransferFunction> (new GammaTransferFunction (2.6))
+ );
+ return *c;
+}
+
ColourConversion::ColourConversion (
shared_ptr<const TransferFunction> in,
YUVToRGB yuv_to_rgb,
diff --git a/src/colour_conversion.h b/src/colour_conversion.h
index 47071dd1..f974a182 100644
--- a/src/colour_conversion.h
+++ b/src/colour_conversion.h
@@ -139,6 +139,8 @@ public:
static ColourConversion const & rec601_to_xyz ();
static ColourConversion const & rec709_to_xyz ();
static ColourConversion const & p3_to_xyz ();
+ static ColourConversion const & rec1886_to_xyz ();
+ static ColourConversion const & rec2020_to_xyz ();
protected:
/** Input transfer function (probably a gamma function, or something similar) */
diff --git a/src/cpl.cc b/src/cpl.cc
index c408fe97..0d8221e2 100644
--- a/src/cpl.cc
+++ b/src/cpl.cc
@@ -45,6 +45,9 @@ using boost::optional;
using boost::dynamic_pointer_cast;
using namespace dcp;
+static string const cpl_interop_ns = "http://www.digicine.com/PROTO-ASDCP-CPL-20040511#";
+static string const cpl_smpte_ns = "http://www.smpte-ra.org/schemas/429-7/2006/CPL";
+
CPL::CPL (string annotation_text, ContentKind content_kind)
: _annotation_text (annotation_text)
/* default _content_title_text to _annotation_text */
@@ -67,6 +70,14 @@ CPL::CPL (boost::filesystem::path file)
cxml::Document f ("CompositionPlaylist");
f.read_file (file);
+ if (f.namespace_uri() == cpl_interop_ns) {
+ _standard = INTEROP;
+ } else if (f.namespace_uri() == cpl_smpte_ns) {
+ _standard = SMPTE;
+ } else {
+ boost::throw_exception (XMLError ("Unrecognised CPL namespace " + f.namespace_uri()));
+ }
+
_id = remove_urn_uuid (f.string_child ("Id"));
_annotation_text = f.optional_string_child ("AnnotationText").get_value_or ("");
_metadata.issuer = f.optional_string_child ("Issuer").get_value_or ("");
@@ -110,9 +121,9 @@ CPL::write_xml (boost::filesystem::path file, Standard standard, shared_ptr<cons
xmlpp::Document doc;
xmlpp::Element* root;
if (standard == INTEROP) {
- root = doc.create_root_node ("CompositionPlaylist", "http://www.digicine.com/PROTO-ASDCP-CPL-20040511#");
+ root = doc.create_root_node ("CompositionPlaylist", cpl_interop_ns);
} else {
- root = doc.create_root_node ("CompositionPlaylist", "http://www.smpte-ra.org/schemas/429-7/2006/CPL");
+ root = doc.create_root_node ("CompositionPlaylist", cpl_smpte_ns);
}
if (signer) {
diff --git a/src/cpl.h b/src/cpl.h
index 9d22cbd4..5ff320d2 100644
--- a/src/cpl.h
+++ b/src/cpl.h
@@ -114,6 +114,10 @@ public:
int64_t duration () const;
+ boost::optional<Standard> standard () const {
+ return _standard;
+ }
+
protected:
/** @return type string for PKLs for this asset */
std::string pkl_type (Standard standard) const;
@@ -129,6 +133,9 @@ private:
std::string _content_version_id; ///< &lt;Id&gt; in &lt;ContentVersion&gt;
std::string _content_version_label_text; ///< &lt;LabelText&gt; in &lt;ContentVersion&gt;
std::list<boost::shared_ptr<Reel> > _reels;
+
+ /** Standard of CPL that was read in */
+ boost::optional<Standard> _standard;
};
}
diff --git a/src/dcp.cc b/src/dcp.cc
index 7ec7577f..11146562 100644
--- a/src/dcp.cc
+++ b/src/dcp.cc
@@ -64,6 +64,13 @@ using boost::dynamic_pointer_cast;
using boost::algorithm::starts_with;
using namespace dcp;
+static string const assetmap_interop_ns = "http://www.digicine.com/PROTO-ASDCP-AM-20040311#";
+static string const assetmap_smpte_ns = "http://www.smpte-ra.org/schemas/429-9/2007/AM";
+static string const pkl_interop_ns = "http://www.digicine.com/PROTO-ASDCP-PKL-20040311#";
+static string const pkl_smpte_ns = "http://www.smpte-ra.org/schemas/429-8/2007/PKL";
+static string const volindex_interop_ns = "http://www.digicine.com/PROTO-ASDCP-AM-20040311#";
+static string const volindex_smpte_ns = "http://www.smpte-ra.org/schemas/429-9/2007/AM";
+
DCP::DCP (boost::filesystem::path directory)
: _directory (directory)
{
@@ -74,6 +81,7 @@ DCP::DCP (boost::filesystem::path directory)
_directory = boost::filesystem::canonical (_directory);
}
+/** Call this instead of throwing an exception if the error can be tolerated */
template<class T> void
survivable_error (bool keep_going, dcp::DCP::ReadErrors* errors, T const & e)
{
@@ -101,7 +109,16 @@ DCP::read (bool keep_going, ReadErrors* errors, bool ignore_incorrect_picture_mx
}
cxml::Document asset_map ("AssetMap");
+
asset_map.read_file (asset_map_file);
+ if (asset_map.namespace_uri() == assetmap_interop_ns) {
+ _standard = INTEROP;
+ } else if (asset_map.namespace_uri() == assetmap_smpte_ns) {
+ _standard = SMPTE;
+ } else {
+ boost::throw_exception (XMLError ("Unrecognised Assetmap namespace " + asset_map.namespace_uri()));
+ }
+
list<shared_ptr<cxml::Node> > asset_nodes = asset_map.node_child("AssetList")->node_children ("Asset");
map<string, boost::filesystem::path> paths;
BOOST_FOREACH (shared_ptr<cxml::Node> i, asset_nodes) {
@@ -146,11 +163,23 @@ DCP::read (bool keep_going, ReadErrors* errors, bool ignore_incorrect_picture_mx
delete p;
if (root == "CompositionPlaylist") {
- _cpls.push_back (shared_ptr<CPL> (new CPL (path)));
+ shared_ptr<CPL> cpl (new CPL (path));
+ if (_standard && cpl->standard() && cpl->standard().get() != _standard.get()) {
+ survivable_error (keep_going, errors, MismatchedStandardError ());
+ }
+ _cpls.push_back (cpl);
} else if (root == "DCSubtitle") {
+ if (_standard && _standard.get() == SMPTE) {
+ survivable_error (keep_going, errors, MismatchedStandardError ());
+ }
other_assets.push_back (shared_ptr<InteropSubtitleAsset> (new InteropSubtitleAsset (path)));
}
} else if (boost::filesystem::extension (path) == ".mxf") {
+
+ /* XXX: asdcplib does not appear to support discovery of read MXFs standard
+ (Interop / SMPTE)
+ */
+
ASDCP::EssenceType_t type;
if (ASDCP::EssenceType (path.string().c_str(), type) != ASDCP::RESULT_OK) {
throw DCPReadError ("Could not find essence type");
@@ -270,9 +299,9 @@ DCP::write_pkl (Standard standard, string pkl_uuid, XMLMetadata metadata, shared
xmlpp::Document doc;
xmlpp::Element* pkl;
if (standard == INTEROP) {
- pkl = doc.create_root_node("PackingList", "http://www.digicine.com/PROTO-ASDCP-PKL-20040311#");
+ pkl = doc.create_root_node("PackingList", pkl_interop_ns);
} else {
- pkl = doc.create_root_node("PackingList", "http://www.smpte-ra.org/schemas/429-8/2007/PKL");
+ pkl = doc.create_root_node("PackingList", pkl_smpte_ns);
}
if (signer) {
@@ -325,10 +354,10 @@ DCP::write_volindex (Standard standard) const
switch (standard) {
case INTEROP:
- root = doc.create_root_node ("VolumeIndex", "http://www.digicine.com/PROTO-ASDCP-AM-20040311#");
+ root = doc.create_root_node ("VolumeIndex", volindex_interop_ns);
break;
case SMPTE:
- root = doc.create_root_node ("VolumeIndex", "http://www.smpte-ra.org/schemas/429-9/2007/AM");
+ root = doc.create_root_node ("VolumeIndex", volindex_smpte_ns);
break;
default:
DCP_ASSERT (false);
@@ -359,10 +388,10 @@ DCP::write_assetmap (Standard standard, string pkl_uuid, int pkl_length, XMLMeta
switch (standard) {
case INTEROP:
- root = doc.create_root_node ("AssetMap", "http://www.digicine.com/PROTO-ASDCP-AM-20040311#");
+ root = doc.create_root_node ("AssetMap", assetmap_interop_ns);
break;
case SMPTE:
- root = doc.create_root_node ("AssetMap", "http://www.smpte-ra.org/schemas/429-9/2007/AM");
+ root = doc.create_root_node ("AssetMap", assetmap_smpte_ns);
break;
default:
DCP_ASSERT (false);
diff --git a/src/dcp.h b/src/dcp.h
index 05c2026b..7d6d1567 100644
--- a/src/dcp.h
+++ b/src/dcp.h
@@ -102,6 +102,11 @@ public:
void resolve_refs (std::list<boost::shared_ptr<Asset> > assets);
+ /** @return Standard of a DCP that was read in */
+ boost::optional<Standard> standard () const {
+ return _standard;
+ }
+
private:
/** Write the PKL file.
@@ -126,6 +131,9 @@ private:
boost::filesystem::path _directory;
/** the CPLs that make up this DCP */
std::list<boost::shared_ptr<CPL> > _cpls;
+
+ /** Standard of DCP that was read in */
+ boost::optional<Standard> _standard;
};
}
diff --git a/src/exceptions.cc b/src/exceptions.cc
index ed6edaa4..14ae8e9c 100644
--- a/src/exceptions.cc
+++ b/src/exceptions.cc
@@ -70,3 +70,9 @@ ProgrammingError::ProgrammingError (string file, int line)
{
}
+
+MismatchedStandardError::MismatchedStandardError ()
+ : DCPReadError ("DCP contains both Interop and SMPTE parts")
+{
+
+}
diff --git a/src/exceptions.h b/src/exceptions.h
index 801bfb01..3410337e 100644
--- a/src/exceptions.h
+++ b/src/exceptions.h
@@ -153,6 +153,12 @@ public:
ProgrammingError (std::string file, int line);
};
+class MismatchedStandardError : public DCPReadError
+{
+public:
+ MismatchedStandardError ();
+};
+
}
#endif
diff --git a/src/modified_gamma_transfer_function.h b/src/modified_gamma_transfer_function.h
index e8875d4b..c200743a 100644
--- a/src/modified_gamma_transfer_function.h
+++ b/src/modified_gamma_transfer_function.h
@@ -25,10 +25,15 @@
namespace dcp {
-/** A transfer function which for an input x gives an output y where
+/** A transfer function which for an input x gives a linear output y where
*
* y = x / B for x <= threshold
* y = ((x + A) / (1 + A))^power for x > threshold
+ *
+ * The reverse transform is
+ *
+ * x = y * B for y <= threshold / B
+ * x = (1 + A) * y ^ (1 / power) - A for y > threshold / B
*/
class ModifiedGammaTransferFunction : public TransferFunction
{