summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorCarl Hetherington <cth@carlh.net>2014-01-26 21:35:02 +0000
committerCarl Hetherington <cth@carlh.net>2014-01-26 21:35:02 +0000
commit59886567974bd3e79d30a4a9425d86d50bf425f3 (patch)
tree68e583a64144f5cbffede882e1187ecf737b2e43 /src
parent0703842433013ac1d5f79c09d7a8361dc2e565c8 (diff)
It builds again.
Diffstat (limited to 'src')
-rw-r--r--src/argb_frame.cc6
-rw-r--r--src/argb_frame.h12
-rw-r--r--src/asset.cc64
-rw-r--r--src/asset.h42
-rw-r--r--src/certificates.cc51
-rw-r--r--src/certificates.h26
-rw-r--r--src/content.cc59
-rw-r--r--src/content.h66
-rw-r--r--src/cpl.cc248
-rw-r--r--src/cpl.h60
-rw-r--r--src/dcp.cc420
-rw-r--r--src/dcp.h80
-rw-r--r--src/exceptions.cc12
-rw-r--r--src/exceptions.h27
-rw-r--r--src/file.cc38
-rw-r--r--src/file.h43
-rw-r--r--src/font.cc (renamed from src/parse/subtitle.cc)64
-rw-r--r--src/font.h (renamed from src/parse/subtitle.h)65
-rw-r--r--src/gamma_lut.cc6
-rw-r--r--src/gamma_lut.h2
-rw-r--r--src/kdm.cc2
-rw-r--r--src/key.h1
-rw-r--r--src/load_font.cc30
-rw-r--r--src/load_font.h38
-rw-r--r--src/mono_picture_mxf.cc12
-rw-r--r--src/mono_picture_mxf.h6
-rw-r--r--src/mono_picture_mxf_writer.cc12
-rw-r--r--src/mono_picture_mxf_writer.h2
-rw-r--r--src/mxf.cc41
-rw-r--r--src/mxf.h29
-rw-r--r--src/mxf_writer.cc46
-rw-r--r--src/mxf_writer.h46
-rw-r--r--src/object.cc4
-rw-r--r--src/object.h6
-rw-r--r--src/parse/asset_map.cc79
-rw-r--r--src/parse/asset_map.h81
-rw-r--r--src/parse/cpl.cc151
-rw-r--r--src/parse/cpl.h163
-rw-r--r--src/parse/pkl.cc52
-rw-r--r--src/picture_mxf.cc35
-rw-r--r--src/picture_mxf.h22
-rw-r--r--src/picture_mxf_writer.cc20
-rw-r--r--src/picture_mxf_writer.h31
-rw-r--r--src/picture_mxf_writer_common.cc6
-rw-r--r--src/reel.cc70
-rw-r--r--src/reel.h48
-rw-r--r--src/reel_asset.cc101
-rw-r--r--src/reel_asset.h82
-rw-r--r--src/reel_mono_picture_asset.cc49
-rw-r--r--src/reel_mono_picture_asset.h40
-rw-r--r--src/reel_picture_asset.cc88
-rw-r--r--src/reel_picture_asset.h52
-rw-r--r--src/reel_sound_asset.cc44
-rw-r--r--src/reel_sound_asset.h42
-rw-r--r--src/reel_stereo_picture_asset.cc50
-rw-r--r--src/reel_stereo_picture_asset.h37
-rw-r--r--src/reel_subtitle_asset.cc44
-rw-r--r--src/reel_subtitle_asset.h (renamed from src/parse/pkl.h)42
-rw-r--r--src/ref.h91
-rw-r--r--src/signer.cc50
-rw-r--r--src/signer.h18
-rw-r--r--src/sound_mxf.cc112
-rw-r--r--src/sound_mxf.h47
-rw-r--r--src/sound_mxf_writer.cc122
-rw-r--r--src/sound_mxf_writer.h55
-rw-r--r--src/stereo_picture_frame.cc2
-rw-r--r--src/stereo_picture_mxf.cc96
-rw-r--r--src/stereo_picture_mxf.h5
-rw-r--r--src/stereo_picture_mxf_writer.cc21
-rw-r--r--src/stereo_picture_mxf_writer.h9
-rw-r--r--src/subtitle.cc60
-rw-r--r--src/subtitle.h55
-rw-r--r--src/subtitle_asset.h198
-rw-r--r--src/subtitle_content.cc (renamed from src/subtitle_asset.cc)171
-rw-r--r--src/subtitle_content.h104
-rw-r--r--src/subtitle_string.cc107
-rw-r--r--src/subtitle_string.h124
-rw-r--r--src/text.cc41
-rw-r--r--src/text.h48
-rw-r--r--src/types.h9
-rw-r--r--src/util.cc36
-rw-r--r--src/util.h4
-rw-r--r--src/wscript20
83 files changed, 2629 insertions, 2071 deletions
diff --git a/src/argb_frame.cc b/src/argb_frame.cc
index 79637329..99d6c814 100644
--- a/src/argb_frame.cc
+++ b/src/argb_frame.cc
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2012 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -17,6 +17,10 @@
*/
+/** @file src/argb_frame.cc
+ * @brief ARGBFrame class.
+ */
+
#include "argb_frame.h"
using namespace dcp;
diff --git a/src/argb_frame.h b/src/argb_frame.h
index 2ad6f69d..a1b3b427 100644
--- a/src/argb_frame.h
+++ b/src/argb_frame.h
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2012 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -18,11 +18,11 @@
*/
/** @file src/argb_frame.h
- * @brief Container for a single image from a picture asset.
+ * @brief ARGBFrame class.
*/
-#include <stdint.h>
#include "util.h"
+#include <stdint.h>
namespace dcp
{
@@ -42,7 +42,7 @@ namespace dcp
*
* Lines are packed so that the second row directly follows the first.
*/
-class ARGBFrame
+class ARGBFrame : boost::noncopyable
{
public:
ARGBFrame (Size size);
@@ -60,8 +60,8 @@ public:
}
private:
- Size _size;
- uint8_t* _data;
+ Size _size; ///< frame size in pixels
+ uint8_t* _data; ///< pointer to image data
};
}
diff --git a/src/asset.cc b/src/asset.cc
index 0147eba2..74e32cf0 100644
--- a/src/asset.cc
+++ b/src/asset.cc
@@ -17,18 +17,82 @@
*/
+/** @file src/asset.cc
+ * @brief Asset class.
+ */
+
#include "asset.h"
+#include "util.h"
+#include <libxml++/libxml++.h>
+#include <boost/lexical_cast.hpp>
using std::string;
+using boost::lexical_cast;
+using boost::function;
using namespace dcp;
+/** Create an Asset with a randomly-generated ID */
Asset::Asset ()
{
}
+Asset::Asset (boost::filesystem::path file)
+ : _file (file)
+{
+
+}
+
+/** Create an Asset with a specified ID.
+ * @param id ID to use.
+ */
Asset::Asset (string id)
: Object (id)
{
}
+
+void
+Asset::write_to_pkl (xmlpp::Node* node) const
+{
+ xmlpp::Node* asset = node->add_child ("Asset");
+ asset->add_child("Id")->add_child_text ("urn:uuid:" + _id);
+ asset->add_child("AnnotationText")->add_child_text (_id);
+ asset->add_child("Hash")->add_child_text (hash ());
+ asset->add_child("Size")->add_child_text (lexical_cast<string> (boost::filesystem::file_size (_file)));
+ asset->add_child("Type")->add_child_text (pkl_type ());
+}
+
+void
+Asset::write_to_assetmap (xmlpp::Node* node) const
+{
+ xmlpp::Node* asset = node->add_child ("Asset");
+ asset->add_child("Id")->add_child_text ("urn:uuid:" + _id);
+ xmlpp::Node* chunk_list = asset->add_child ("ChunkList");
+ xmlpp::Node* chunk = chunk_list->add_child ("Chunk");
+ chunk->add_child("Path")->add_child_text (_file.string ());
+ chunk->add_child("VolumeIndex")->add_child_text ("1");
+ chunk->add_child("Offset")->add_child_text ("0");
+ chunk->add_child("Length")->add_child_text (lexical_cast<string> (boost::filesystem::file_size (_file)));
+}
+
+string
+Asset::hash () const
+{
+ if (!_hash.empty ()) {
+ _hash = make_digest (_file, 0);
+ }
+
+ return _hash;
+}
+
+bool
+Asset::equals (boost::shared_ptr<const Asset> other, EqualityOptions, function<void (NoteType, string)> note) const
+{
+ if (_hash != other->_hash) {
+ note (ERROR, "Asset hashes differ");
+ return false;
+ }
+
+ return true;
+}
diff --git a/src/asset.h b/src/asset.h
index f3546cd8..e8867ae5 100644
--- a/src/asset.h
+++ b/src/asset.h
@@ -17,23 +17,61 @@
*/
+/** @file src/asset.h
+ * @brief Asset class.
+ */
+
#ifndef LIBDCP_ASSET_H
#define LIBDCP_ASSET_H
#include "object.h"
+#include "types.h"
+#include <boost/filesystem.hpp>
+#include <boost/function.hpp>
+
+namespace xmlpp {
+ class Node;
+}
namespace dcp {
/** @class Asset
- * @brief Parent class for DCP assets, i.e. picture/sound/subtitles, CPLs and PKLs.
+ * @brief Parent class for DCP assets, i.e. picture/sound/subtitles and CPLs.
+ *
+ * Note that this class is not used for ReelAssets; they are just for the metadata
+ * that gets put into <Reel>s.
*/
-
class Asset : public Object
{
public:
Asset ();
+ Asset (boost::filesystem::path file);
Asset (std::string id);
+ virtual std::string pkl_type () const = 0;
+ virtual bool equals (boost::shared_ptr<const Asset> other, EqualityOptions opt, boost::function<void (NoteType, std::string)> note) const;
+
+ /** Write details of the asset to a PKL AssetList node.
+ * @param node Parent node.
+ */
+ void write_to_pkl (xmlpp::Node* node) const;
+ void write_to_assetmap (xmlpp::Node* node) const;
+
+ boost::filesystem::path file () const {
+ return _file;
+ }
+
+ void set_file (boost::filesystem::path file) {
+ _file = file;
+ }
+
+ std::string hash () const;
+
+protected:
+ friend class MXFWriter;
+
+ boost::filesystem::path _file;
+ mutable std::string _hash;
};
}
diff --git a/src/certificates.cc b/src/certificates.cc
index caa4c830..222352f2 100644
--- a/src/certificates.cc
+++ b/src/certificates.cc
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2012 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -17,25 +17,21 @@
*/
-#include <sstream>
-#include <vector>
-#include <cerrno>
-#include <boost/algorithm/string.hpp>
-#include <openssl/x509.h>
-#include <openssl/ssl.h>
-#include <openssl/asn1.h>
-#include <openssl/err.h>
-#include <libxml++/nodes/element.h>
#include "KM_util.h"
#include "certificates.h"
#include "compose.hpp"
#include "exceptions.h"
#include "util.h"
+#include <libxml++/nodes/element.h>
+#include <openssl/x509.h>
+#include <openssl/ssl.h>
+#include <openssl/asn1.h>
+#include <openssl/err.h>
+#include <boost/algorithm/string.hpp>
+#include <cerrno>
using std::list;
using std::string;
-using std::stringstream;
-using std::vector;
using boost::shared_ptr;
using namespace dcp;
@@ -47,6 +43,9 @@ Certificate::Certificate (X509* c)
}
+/** Load an X509 certificate from a file.
+ * @param filename File to load.
+ */
Certificate::Certificate (boost::filesystem::path filename)
: _certificate (0)
, _public_key (0)
@@ -61,6 +60,9 @@ Certificate::Certificate (boost::filesystem::path filename)
}
}
+/** Load an X509 certificate from a string.
+ * @param cert String to read from.
+ */
Certificate::Certificate (string cert)
: _certificate (0)
, _public_key (0)
@@ -68,6 +70,9 @@ Certificate::Certificate (string cert)
read_string (cert);
}
+/** Copy constructor.
+ * @param other Certificate to copy.
+ */
Certificate::Certificate (Certificate const & other)
: _certificate (0)
, _public_key (0)
@@ -75,6 +80,9 @@ Certificate::Certificate (Certificate const & other)
read_string (other.certificate (true));
}
+/** Read a certificate from a string.
+ * @param cert String to read.
+ */
void
Certificate::read_string (string cert)
{
@@ -91,12 +99,16 @@ Certificate::read_string (string cert)
BIO_free (bio);
}
+/** Destructor */
Certificate::~Certificate ()
{
X509_free (_certificate);
RSA_free (_public_key);
}
+/** operator= for Certificate.
+ * @param other Certificate to read from.
+ */
Certificate &
Certificate::operator= (Certificate const & other)
{
@@ -114,6 +126,10 @@ Certificate::operator= (Certificate const & other)
return *this;
}
+/** Return the certificate as a string.
+ * @param with_begin_end true to include the -----BEGIN CERTIFICATE--- / -----END CERTIFICATE----- markers.
+ * @return Certificate string.
+ */
string
Certificate::certificate (bool with_begin_end) const
{
@@ -143,6 +159,10 @@ Certificate::certificate (bool with_begin_end) const
return s;
}
+/** @return Certificate's issuer, in the form
+ * dnqualifier=<dnQualififer>,CN=<commonName>,OU=<organizationalUnitName>,O=organizationName
+ * and with + signs escaped to \+
+ */
string
Certificate::issuer () const
{
@@ -244,6 +264,7 @@ Certificate::thumbprint () const
return Kumu::base64encode (digest, 20, digest_base64, 64);
}
+/** @return RSA public key from this Certificate. Caller must not free the returned value. */
RSA *
Certificate::public_key () const
{
@@ -266,6 +287,7 @@ Certificate::public_key () const
return _public_key;
}
+/** @return Root certificate */
shared_ptr<Certificate>
CertificateChain::root () const
{
@@ -273,6 +295,7 @@ CertificateChain::root () const
return _certificates.front ();
}
+/** @return Leaf certificate */
shared_ptr<Certificate>
CertificateChain::leaf () const
{
@@ -280,6 +303,7 @@ CertificateChain::leaf () const
return _certificates.back ();
}
+/** @return Certificates in order from leaf to root */
list<shared_ptr<Certificate> >
CertificateChain::leaf_to_root () const
{
@@ -288,6 +312,9 @@ CertificateChain::leaf_to_root () const
return c;
}
+/** Add a certificate to the end of the chain.
+ * @param c Certificate to add.
+ */
void
CertificateChain::add (shared_ptr<Certificate> c)
{
diff --git a/src/certificates.h b/src/certificates.h
index c7d6698b..8ec5ddd5 100644
--- a/src/certificates.h
+++ b/src/certificates.h
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2012 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -17,16 +17,20 @@
*/
+/** @file src/certificates.h
+ * @brief Certificate and CertificateChain classes.
+ */
+
#ifndef LIBDCP_CERTIFICATES_H
#define LIBDCP_CERTIFICATES_H
-#include <string>
-#include <list>
+#undef X509_NAME
+#include <openssl/x509.h>
#include <boost/noncopyable.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/filesystem.hpp>
-#undef X509_NAME
-#include <openssl/x509.h>
+#include <string>
+#include <list>
class certificates;
@@ -36,6 +40,11 @@ namespace xmlpp {
namespace dcp {
+/** @class Certificate
+ * @brief A wrapper for an X509 certificate.
+ *
+ * This class can take a Certificate from a file, a string or an OpenSSL X509 object.
+ */
class Certificate
{
public:
@@ -51,16 +60,12 @@ public:
Certificate& operator= (Certificate const &);
- /** @param with_begin_end true to include BEGIN CERTIFICATE / END CERTIFICATE markers
- * @return the whole certificate as a string.
- */
std::string certificate (bool with_begin_end = false) const;
std::string issuer () const;
std::string serial () const;
std::string subject () const;
std::string common_name () const;
- /** @return RSA public key from this Certificate. Caller must not free the returned value. */
RSA* public_key () const;
std::string thumbprint () const;
@@ -76,6 +81,9 @@ private:
mutable RSA* _public_key;
};
+/** @class CertificateChain
+ * @brief A chain of any number of certificates, from root to leaf.
+ */
class CertificateChain
{
public:
diff --git a/src/content.cc b/src/content.cc
index 9a035c80..06e2806d 100644
--- a/src/content.cc
+++ b/src/content.cc
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2012 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -33,59 +33,36 @@ using namespace boost;
using namespace dcp;
Content::Content (boost::filesystem::path file)
- : _file (file)
- , _edit_rate (0)
+ : Asset (file)
+ , _edit_rate (24, 1)
, _intrinsic_duration (0)
{
}
-Content::Content (int edit_rate)
+Content::Content (Fraction edit_rate)
: _edit_rate (edit_rate)
, _intrinsic_duration (0)
{
}
-void
-Content::write_to_pkl (xmlpp::Node* node) const
-{
- xmlpp::Node* asset = node->add_child ("Asset");
- asset->add_child("Id")->add_child_text ("urn:uuid:" + _id);
- asset->add_child("AnnotationText")->add_child_text (_id);
-//XXX asset->add_child("Hash")->add_child_text (digest ());
- asset->add_child("Size")->add_child_text (lexical_cast<string> (filesystem::file_size (_file)));
- asset->add_child("Type")->add_child_text ("application/mxf");
-}
-
-void
-Content::write_to_assetmap (xmlpp::Node* node) const
-{
- xmlpp::Node* asset = node->add_child ("Asset");
- asset->add_child("Id")->add_child_text ("urn:uuid:" + _id);
- xmlpp::Node* chunk_list = asset->add_child ("ChunkList");
- xmlpp::Node* chunk = chunk_list->add_child ("Chunk");
- chunk->add_child("Path")->add_child_text (_file.string ());
- chunk->add_child("VolumeIndex")->add_child_text ("1");
- chunk->add_child("Offset")->add_child_text ("0");
- chunk->add_child("Length")->add_child_text (lexical_cast<string> (filesystem::file_size (_file)));
-}
-
bool
-Content::equals (shared_ptr<const Content> other, EqualityOptions, boost::function<void (NoteType, string)> note) const
+Content::equals (shared_ptr<const Content> other, EqualityOptions opt, boost::function<void (NoteType, string)> note) const
{
- // if (_edit_rate != other->_edit_rate) {
- // note (ERROR, "asset edit rates differ");
- // return false;
- // }
+ if (!Asset::equals (other, opt, note)) {
+ return false;
+ }
- // if (_intrinsic_duration != other->_intrinsic_duration) {
- // note (ERROR, "asset intrinsic durations differ");
- // }
-
- // if (_duration != other->_duration) {
- // note (ERROR, "asset durations differ");
- // }
+ if (_edit_rate != other->_edit_rate) {
+ note (ERROR, "content edit rates differ");
+ return false;
+ }
+
+ if (_intrinsic_duration != other->_intrinsic_duration) {
+ note (ERROR, "asset intrinsic durations differ");
+ return false;
+ }
- // return true;
+ return true;
}
diff --git a/src/content.h b/src/content.h
index 75e39a01..57aaa14c 100644
--- a/src/content.h
+++ b/src/content.h
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2012 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -17,16 +17,20 @@
*/
+/** @file src/content.h
+ * @brief Content class.
+ */
+
#ifndef LIBDCP_CONTENT_H
#define LIBDCP_CONTENT_H
-#include <string>
-#include <list>
-#include <boost/filesystem.hpp>
-#include <boost/function.hpp>
-#include <libxml++/libxml++.h>
#include "types.h"
#include "asset.h"
+#include <libxml++/libxml++.h>
+#include <boost/filesystem.hpp>
+#include <boost/function.hpp>
+#include <string>
+#include <list>
namespace ASDCP {
class WriterInfo;
@@ -48,65 +52,25 @@ class Content : public Asset
{
public:
Content (boost::filesystem::path file);
- Content (int edit_rate);
+ Content (Fraction edit_rate);
virtual ~Content () {}
- /** Write details of the asset to a PKL AssetList node.
- * @param p Parent node.
- */
- void write_to_pkl (xmlpp::Node *) const;
-
- /** Write details of the asset to a ASSETMAP stream.
- * @param s Stream.
- */
- void write_to_assetmap (xmlpp::Node *) const;
-
- boost::filesystem::path file () const {
- return _file;
- }
-
- void set_file (boost::filesystem::path file) {
- _file = file;
- }
-
- int edit_rate () const {
+ Fraction edit_rate () const {
return _edit_rate;
}
- void set_edit_rate (int r) {
- _edit_rate = r;
- }
-
- void set_entry_point (int64_t p) {
- _entry_point = p;
- }
-
int64_t intrinsic_duration () const {
return _intrinsic_duration;
}
- void set_intrinsic_duration (int64_t d) {
- _intrinsic_duration = d;
- }
-
- int64_t duration () const {
- return _duration;
- }
-
- void set_duration (int64_t d) {
- _duration = d;
- }
-
virtual bool equals (boost::shared_ptr<const Content> other, EqualityOptions opt, boost::function<void (NoteType, std::string)>) const;
protected:
- boost::filesystem::path _file;
- /** The edit rate; this is normally equal to the number of video frames per second */
- int _edit_rate;
- int64_t _entry_point;
+ friend class MXFWriter;
+
+ Fraction _edit_rate;
int64_t _intrinsic_duration;
- int64_t _duration;
};
}
diff --git a/src/cpl.cc b/src/cpl.cc
index 9f7ef7b3..0cd1d6ce 100644
--- a/src/cpl.cc
+++ b/src/cpl.cc
@@ -17,20 +17,22 @@
*/
-#include <libxml/parser.h>
#include "cpl.h"
-#include "parse/cpl.h"
#include "util.h"
#include "mono_picture_mxf.h"
#include "stereo_picture_mxf.h"
#include "sound_mxf.h"
-#include "subtitle_asset.h"
-#include "parse/asset_map.h"
+#include "subtitle_content.h"
#include "reel.h"
#include "metadata.h"
#include "signer.h"
#include "exceptions.h"
+#include "xml.h"
#include "compose.hpp"
+#include "reel_picture_asset.h"
+#include "reel_sound_asset.h"
+#include "reel_subtitle_asset.h"
+#include <libxml/parser.h>
using std::string;
using std::stringstream;
@@ -43,165 +45,56 @@ using boost::lexical_cast;
using boost::optional;
using namespace dcp;
-CPL::CPL (boost::filesystem::path directory, string name, ContentKind content_kind, int length, int frames_per_second)
- : _directory (directory)
- , _name (name)
+CPL::CPL (string annotation_text, ContentKind content_kind)
+ : _annotation_text (annotation_text)
, _content_kind (content_kind)
- , _length (length)
- , _fps (frames_per_second)
+ , _length (0)
{
}
-/** Construct a CPL object from a XML file.
- * @param directory The directory containing this CPL's DCP.
- * @param file The CPL XML filename.
- * @param asset_maps AssetMaps to look for assets in.
- * @param require_mxfs true to throw an exception if a required MXF file does not exist.
- */
-CPL::CPL (boost::filesystem::path directory, string file, list<PathAssetMap> asset_maps, bool require_mxfs)
- : _directory (directory)
- , _content_kind (FEATURE)
+/** Construct a CPL object from a XML file */
+CPL::CPL (boost::filesystem::path file)
+ : _content_kind (FEATURE)
, _length (0)
- , _fps (0)
{
- /* Read the XML */
- shared_ptr<parse::CPL> cpl;
- try {
- cpl.reset (new parse::CPL (file));
- } catch (FileError& e) {
- boost::throw_exception (FileError ("could not load CPL file", file, e.number ()));
- }
-
- /* Now cherry-pick the required bits into our own data structure */
-
- _name = cpl->annotation_text;
- _content_kind = cpl->content_kind;
-
- /* Trim urn:uuid: off the front */
- _id = cpl->id.substr (9);
-
- for (list<shared_ptr<parse::Reel> >::iterator i = cpl->reels.begin(); i != cpl->reels.end(); ++i) {
-
- shared_ptr<parse::Picture> p;
-
- if ((*i)->asset_list->main_picture) {
- p = (*i)->asset_list->main_picture;
- } else {
- p = (*i)->asset_list->main_stereoscopic_picture;
- }
-
- _fps = p->edit_rate.numerator;
- _length += p->duration;
-
- shared_ptr<PictureMXF> picture;
- shared_ptr<SoundMXF> sound;
- shared_ptr<SubtitleAsset> subtitle;
-
- /* Some rather twisted logic to decide if we are 3D or not;
- some DCPs give a MainStereoscopicPicture to indicate 3D, others
- just have a FrameRate twice the EditRate and apparently
- expect you to divine the fact that they are hence 3D.
- */
-
- if (!(*i)->asset_list->main_stereoscopic_picture && p->edit_rate == p->frame_rate) {
-
- try {
- pair<string, shared_ptr<const parse::AssetMapAsset> > asset = asset_from_id (asset_maps, p->id);
-
-// picture.reset (new MonoPictureMXF (asset.first, asset.second->chunks.front()->path));
-
-// picture->read ();
-// picture->set_edit_rate (_fps);
-// picture->set_entry_point (p->entry_point);
-// picture->set_duration (p->duration);
- if (p->key_id.length() > 9) {
- /* Trim urn:uuid: */
-// picture->set_key_id (p->key_id.substr (9));
- }
- } catch (MXFFileError) {
- if (require_mxfs) {
- throw;
- }
- }
-
- } else {
- try {
- pair<string, shared_ptr<const parse::AssetMapAsset> > asset = asset_from_id (asset_maps, p->id);
-
-// picture.reset (new StereoPictureMXF (asset.first, asset.second->chunks.front()->path));
-
-// picture->read ();
-// picture->set_edit_rate (_fps);
-// picture->set_entry_point (p->entry_point);
-// picture->set_duration (p->duration);
- if (p->key_id.length() > 9) {
- /* Trim urn:uuid: */
-// picture->set_key_id (p->key_id.substr (9));
- }
-
- } catch (MXFFileError) {
- if (require_mxfs) {
- throw;
- }
- }
-
- }
-
- if ((*i)->asset_list->main_sound) {
-
- try {
- pair<string, shared_ptr<const parse::AssetMapAsset> > asset = asset_from_id (asset_maps, (*i)->asset_list->main_sound->id);
-
-// sound.reset (new SoundMXF (asset.first, asset.second->chunks.front()->path));
-// shared_ptr<parse::MainSound> s = (*i)->asset_list->main_sound;
-
-// sound->read ();
-// sound->set_entry_point (s->entry_point);
-// sound->set_duration (s->duration);
-// if (s->key_id.length() > 9) {
- /* Trim urn:uuid: */
-// sound->set_key_id (s->key_id.substr (9));
-// }
- } catch (MXFFileError) {
- if (require_mxfs) {
- throw;
- }
- }
- }
-
- if ((*i)->asset_list->main_subtitle) {
-
-// pair<string, shared_ptr<const parse::AssetMapAsset> > asset = asset_from_id (asset_maps, (*i)->asset_list->main_subtitle->id);
-
-// subtitle.reset (new SubtitleAsset (asset.first, asset.second->chunks.front()->path));
-
-// subtitle->set_entry_point ((*i)->asset_list->main_subtitle->entry_point);
-// subtitle->set_duration ((*i)->asset_list->main_subtitle->duration);
- }
-
-// _reels.push_back (shared_ptr<Reel> (new Reel (picture, sound, subtitle)));
- }
+ cxml::Document f ("CompositionPlaylist");
+ f.read_file (file);
+
+ _id = f.string_child ("Id");
+ _annotation_text = f.optional_string_child ("AnnotationText").get_value_or ("");
+ _issue_date = f.string_child ("IssueDate");
+ _creator = f.optional_string_child ("Creator").get_value_or ("");
+ _content_title_text = f.string_child ("ContentTitleText");
+ _content_kind = content_kind_from_string (f.string_child ("ContentKind"));
+ shared_ptr<cxml::Node> content_version = f.node_child ("ContentVersion");
+ if (content_version) {
+ _content_version_id = content_version->optional_string_child ("Id").get_value_or ("");
+ _content_version_label_text = content_version->string_child ("LabelText");
+ content_version->done ();
+ }
+ f.ignore_child ("RatingList");
+ _reels = type_grand_children<Reel> (f, "ReelList", "Reel");
+
+ f.ignore_child ("Issuer");
+ f.ignore_child ("Signer");
+ f.ignore_child ("Signature");
+
+ f.done ();
}
void
-CPL::add_reel (shared_ptr<Reel> reel)
+CPL::add (shared_ptr<Reel> reel)
{
_reels.push_back (reel);
}
void
-CPL::write_xml (bool interop, XMLMetadata const & metadata, shared_ptr<const Signer> signer) const
+CPL::write_xml (boost::filesystem::path file, Standard standard, XMLMetadata metadata, shared_ptr<const Signer> signer) const
{
- boost::filesystem::path p;
- p /= _directory;
- stringstream s;
- s << _id << "_cpl.xml";
- p /= s.str();
-
xmlpp::Document doc;
xmlpp::Element* root;
- if (interop) {
+ if (standard == INTEROP) {
root = doc.create_root_node ("CompositionPlaylist", "http://www.digicine.com/PROTO-ASDCP-CPL-20040511#");
} else {
root = doc.create_root_node ("CompositionPlaylist", "http://www.smpte-ra.org/schemas/429-7/2006/CPL");
@@ -212,44 +105,34 @@ CPL::write_xml (bool interop, XMLMetadata const & metadata, shared_ptr<const Sig
}
root->add_child("Id")->add_child_text ("urn:uuid:" + _id);
- root->add_child("AnnotationText")->add_child_text (_name);
+ root->add_child("AnnotationText")->add_child_text (_annotation_text);
root->add_child("IssueDate")->add_child_text (metadata.issue_date);
root->add_child("Issuer")->add_child_text (metadata.issuer);
root->add_child("Creator")->add_child_text (metadata.creator);
- root->add_child("ContentTitleText")->add_child_text (_name);
+ root->add_child("ContentTitleText")->add_child_text (_content_version_label_text);
root->add_child("ContentKind")->add_child_text (content_kind_to_string (_content_kind));
{
xmlpp::Node* cv = root->add_child ("ContentVersion");
- cv->add_child ("Id")->add_child_text ("urn:uri:" + _id + "_" + metadata.issue_date);
- cv->add_child ("LabelText")->add_child_text (_id + "_" + metadata.issue_date);
+ cv->add_child ("Id")->add_child_text (_content_version_id);
+ cv->add_child ("LabelText")->add_child_text (_content_version_label_text);
}
root->add_child("RatingList");
xmlpp::Element* reel_list = root->add_child ("ReelList");
for (list<shared_ptr<Reel> >::const_iterator i = _reels.begin(); i != _reels.end(); ++i) {
- (*i)->write_to_cpl (reel_list);
+ (*i)->write_to_cpl (reel_list, standard);
}
if (signer) {
- signer->sign (root, interop);
+ signer->sign (root, standard);
}
/* This must not be the _formatted version otherwise signature digests will be wrong */
- doc.write_to_file (p.string (), "UTF-8");
-
- _digest = make_digest (p.string (), 0);
- _length = boost::filesystem::file_size (p.string ());
-}
+ doc.write_to_file (file.string (), "UTF-8");
-void
-CPL::write_to_pkl (xmlpp::Node* node) const
-{
- xmlpp::Node* asset = node->add_child ("Asset");
- asset->add_child("Id")->add_child_text ("urn:uuid:" + _id);
- asset->add_child("Hash")->add_child_text (_digest);
- asset->add_child("Size")->add_child_text (lexical_cast<string> (_length));
- asset->add_child("Type")->add_child_text ("text/xml");
+ _digest = make_digest (file.string (), 0);
+ _length = boost::filesystem::file_size (file.string ());
}
list<shared_ptr<const Content> >
@@ -258,13 +141,13 @@ CPL::assets () const
list<shared_ptr<const Content> > a;
for (list<shared_ptr<Reel> >::const_iterator i = _reels.begin(); i != _reels.end(); ++i) {
if ((*i)->main_picture ()) {
- a.push_back ((*i)->main_picture ());
+ a.push_back ((*i)->main_picture()->mxf ());
}
if ((*i)->main_sound ()) {
- a.push_back ((*i)->main_sound ());
+ a.push_back ((*i)->main_sound()->mxf ());
}
if ((*i)->main_subtitle ()) {
- a.push_back ((*i)->main_subtitle ());
+ a.push_back ((*i)->main_subtitle()->subtitle_content ());
}
}
@@ -284,14 +167,12 @@ CPL::write_to_assetmap (xmlpp::Node* node) const
chunk->add_child("Length")->add_child_text(lexical_cast<string> (_length));
}
-
-
bool
CPL::equals (CPL const & other, EqualityOptions opt, boost::function<void (NoteType, string)> note) const
{
- if (_name != other._name && !opt.cpl_names_can_differ) {
+ if (_annotation_text != other._annotation_text && !opt.cpl_annotation_texts_can_differ) {
stringstream s;
- s << "names differ: " << _name << " vs " << other._name << "\n";
+ s << "annotation texts differ: " << _annotation_text << " vs " << other._annotation_text << "\n";
note (ERROR, s.str ());
return false;
}
@@ -301,16 +182,6 @@ CPL::equals (CPL const & other, EqualityOptions opt, boost::function<void (NoteT
return false;
}
- if (_fps != other._fps) {
- note (ERROR, String::compose ("frames per second differ (%1 vs %2)", _fps, other._fps));
- return false;
- }
-
- if (_length != other._length) {
- stringstream s;
- note (ERROR, String::compose ("lengths differ (%1 vs %2)", _length, other._length));
- }
-
if (_reels.size() != other._reels.size()) {
note (ERROR, String::compose ("reel counts differ (%1 vs %2)", _reels.size(), other._reels.size()));
return false;
@@ -344,26 +215,13 @@ CPL::encrypted () const
}
void
-CPL::add_kdm (KDM const & kdm)
+CPL::add (KDM const & kdm)
{
for (list<shared_ptr<Reel> >::const_iterator i = _reels.begin(); i != _reels.end(); ++i) {
(*i)->add_kdm (kdm);
}
}
-pair<string, shared_ptr<const parse::AssetMapAsset> >
-CPL::asset_from_id (list<PathAssetMap> asset_maps, string id) const
-{
- for (list<PathAssetMap>::const_iterator i = asset_maps.begin(); i != asset_maps.end(); ++i) {
- shared_ptr<parse::AssetMapAsset> a = i->second->asset_from_id (id);
- if (a) {
- return make_pair (i->first, a);
- }
- }
-
- return make_pair ("", shared_ptr<const parse::AssetMapAsset> ());
-}
-
void
CPL::set_mxf_keys (Key key)
{
diff --git a/src/cpl.h b/src/cpl.h
index abfb92f6..83fc4b9d 100644
--- a/src/cpl.h
+++ b/src/cpl.h
@@ -33,11 +33,6 @@
#include "asset.h"
namespace dcp {
-
-namespace parse {
- class AssetMap;
- class AssetMapAsset;
-}
class Content;
class Reel;
@@ -52,16 +47,23 @@ class KDM;
class CPL : public Asset
{
public:
- CPL (boost::filesystem::path directory, std::string name, ContentKind content_kind, int length, int frames_per_second);
- CPL (boost::filesystem::path, std::string file, std::list<PathAssetMap> asset_maps, bool require_mxfs = true);
+ CPL (std::string annotation_text, ContentKind content_kind);
+ CPL (boost::filesystem::path file);
- void add_reel (boost::shared_ptr<Reel> reel);
-
- /** @return the length in frames */
- int length () const {
- return _length;
+ std::string pkl_type () const {
+ return "text/xml";
}
+ void add (boost::shared_ptr<Reel> reel);
+
+ std::string annotation_text () const {
+ return _annotation_text;
+ }
+
+ std::string content_title_text () const {
+ return _content_title_text;
+ }
+
/** @return the type of the content, used by media servers
* to categorise things (e.g. feature, trailer, etc.)
*/
@@ -73,18 +75,6 @@ public:
return _reels;
}
- /** @return the CPL's name, as will be presented on projector
- * media servers and theatre management systems.
- */
- std::string name () const {
- return _name;
- }
-
- /** @return the number of frames per second */
- int frames_per_second () const {
- return _fps;
- }
-
std::list<boost::shared_ptr<const Content> > assets () const;
bool encrypted () const;
@@ -93,29 +83,27 @@ public:
bool equals (CPL const & other, EqualityOptions options, boost::function<void (NoteType, std::string)> note) const;
- void write_xml (bool, XMLMetadata const &, boost::shared_ptr<const Signer>) const;
+ void write_xml (boost::filesystem::path file, Standard standard, XMLMetadata, boost::shared_ptr<const Signer>) const;
void write_to_assetmap (xmlpp::Node *) const;
- void write_to_pkl (xmlpp::Node *) const;
- void add_kdm (KDM const &);
+ void add (KDM const &);
private:
- std::pair<std::string, boost::shared_ptr<const parse::AssetMapAsset> > asset_from_id (std::list<PathAssetMap>, std::string id) const;
- boost::filesystem::path _directory;
- /** the name of the DCP */
- std::string _name;
- /** the content kind of the CPL */
+ std::string _annotation_text;
+ std::string _issue_date;
+ std::string _creator;
+ std::string _content_title_text;
ContentKind _content_kind;
- /** length in frames */
- mutable int _length;
- /** frames per second */
- int _fps;
+ std::string _content_version_id;
+ std::string _content_version_label_text;
/** reels */
std::list<boost::shared_ptr<Reel> > _reels;
/** a SHA1 digest of our XML */
mutable std::string _digest;
+ /** length in bytes of the XML that we last wrote to disk */
+ mutable int64_t _length;
};
}
diff --git a/src/dcp.cc b/src/dcp.cc
index a5b0c6e4..808c040e 100644
--- a/src/dcp.cc
+++ b/src/dcp.cc
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2012 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -18,33 +18,35 @@
*/
/** @file src/dcp.cc
- * @brief A class to create a DCP.
+ * @brief DCP class.
*/
-#include <sstream>
-#include <iomanip>
-#include <cassert>
-#include <iostream>
-#include <boost/filesystem.hpp>
-#include <boost/lexical_cast.hpp>
-#include <boost/algorithm/string.hpp>
-#include <boost/lexical_cast.hpp>
-#include <libxml++/libxml++.h>
-#include <xmlsec/xmldsig.h>
-#include <xmlsec/app.h>
#include "dcp.h"
#include "sound_mxf.h"
#include "picture_mxf.h"
-#include "subtitle_asset.h"
+#include "subtitle_content.h"
+#include "mono_picture_mxf.h"
+#include "stereo_picture_mxf.h"
#include "util.h"
#include "metadata.h"
#include "exceptions.h"
-#include "parse/pkl.h"
-#include "parse/asset_map.h"
#include "reel.h"
#include "cpl.h"
#include "signer.h"
#include "kdm.h"
+#include "compose.hpp"
+#include "AS_DCP.h"
+#include <xmlsec/xmldsig.h>
+#include <xmlsec/app.h>
+#include <libxml++/libxml++.h>
+#include <boost/filesystem.hpp>
+#include <boost/lexical_cast.hpp>
+#include <boost/algorithm/string.hpp>
+#include <boost/lexical_cast.hpp>
+#include <sstream>
+#include <iomanip>
+#include <cassert>
+#include <iostream>
using std::string;
using std::list;
@@ -53,8 +55,10 @@ using std::ostream;
using std::copy;
using std::back_inserter;
using std::make_pair;
+using std::map;
using boost::shared_ptr;
using boost::lexical_cast;
+using boost::dynamic_pointer_cast;
using namespace dcp;
DCP::DCP (boost::filesystem::path directory)
@@ -64,33 +68,154 @@ DCP::DCP (boost::filesystem::path directory)
}
void
-DCP::write_xml (bool interop, XMLMetadata const & metadata, shared_ptr<const Signer> signer) const
+DCP::read ()
{
- for (list<shared_ptr<CPL> >::const_iterator i = _cpls.begin(); i != _cpls.end(); ++i) {
- (*i)->write_xml (interop, metadata, signer);
+ /* Read the ASSETMAP */
+
+ boost::filesystem::path asset_map_file;
+ if (boost::filesystem::exists (_directory / "ASSETMAP")) {
+ asset_map_file = _directory / "ASSETMAP";
+ } else if (boost::filesystem::exists (_directory / "ASSETMAP.xml")) {
+ asset_map_file = _directory / "ASSETMAP.xml";
+ } else {
+ boost::throw_exception (DCPReadError ("could not find AssetMap file"));
+ }
+
+ cxml::Document asset_map ("AssetMap");
+ asset_map.read_file (asset_map_file);
+ list<shared_ptr<cxml::Node> > assets = asset_map.node_child("AssetList")->node_children ("Asset");
+ map<string, boost::filesystem::path> paths;
+ for (list<shared_ptr<cxml::Node> >::const_iterator i = assets.begin(); i != assets.end(); ++i) {
+ if ((*i)->node_child("ChunkList")->node_children("Chunk").size() != 1) {
+ boost::throw_exception (XMLError ("unsupported asset chunk count"));
+ }
+ paths.insert (make_pair (
+ (*i)->string_child ("Id"),
+ (*i)->node_child("ChunkList")->node_child("Chunk")->string_child ("Path")
+ ));
}
- string pkl_uuid = make_uuid ();
- string pkl_path = write_pkl (pkl_uuid, interop, metadata, signer);
+ /* Read all the assets from the asset map */
- write_volindex (interop);
- write_assetmap (pkl_uuid, boost::filesystem::file_size (pkl_path), interop, metadata);
+ for (map<string, boost::filesystem::path>::const_iterator i = paths.begin(); i != paths.end(); ++i) {
+ if (boost::algorithm::ends_with (i->second.string(), ".xml")) {
+ xmlpp::DomParser* p = new xmlpp::DomParser;
+ try {
+ p->parse_file (i->second.string());
+ } catch (std::exception& e) {
+ delete p;
+ continue;
+ }
+
+ string const root = p->get_document()->get_root_node()->get_name ();
+ delete p;
+
+ if (root == "CompositionPlaylist") {
+ _assets.push_back (shared_ptr<CPL> (new CPL (i->second)));
+ } else if (root == "DCSubtitle") {
+ _assets.push_back (shared_ptr<SubtitleContent> (new SubtitleContent (i->second)));
+ }
+ } else if (boost::algorithm::ends_with (i->second.string(), ".mxf")) {
+ ASDCP::EssenceType_t type;
+ if (ASDCP::EssenceType (i->second.string().c_str(), type) != ASDCP::RESULT_OK) {
+ throw DCPReadError ("Could not find essence type");
+ }
+ switch (type) {
+ case ASDCP::ESS_UNKNOWN:
+ case ASDCP::ESS_MPEG2_VES:
+ throw DCPReadError ("MPEG2 video essences are not supported");
+ case ASDCP::ESS_JPEG_2000:
+ _assets.push_back (shared_ptr<MonoPictureMXF> (new MonoPictureMXF (i->second)));
+ break;
+ case ASDCP::ESS_PCM_24b_48k:
+ case ASDCP::ESS_PCM_24b_96k:
+ _assets.push_back (shared_ptr<SoundMXF> (new SoundMXF (i->second)));
+ break;
+ case ASDCP::ESS_JPEG_2000_S:
+ _assets.push_back (shared_ptr<StereoPictureMXF> (new StereoPictureMXF (i->second)));
+ break;
+ default:
+ throw DCPReadError ("Unknown MXF essence type");
+ }
+ }
+ }
+}
+
+bool
+DCP::equals (DCP const & other, EqualityOptions opt, boost::function<void (NoteType, string)> note) const
+{
+ if (_assets.size() != other._assets.size()) {
+ note (ERROR, "Asset counts differ");
+ return false;
+ }
+
+ list<shared_ptr<Asset> >::const_iterator a = _assets.begin ();
+ list<shared_ptr<Asset> >::const_iterator b = other._assets.begin ();
+
+ while (a != _assets.end ()) {
+ if (!(*a)->equals (*b, opt, note)) {
+ return false;
+ }
+ ++a;
+ ++b;
+ }
+
+ return true;
+}
+
+void
+DCP::add (shared_ptr<Asset> asset)
+{
+ _assets.push_back (asset);
}
-std::string
-DCP::write_pkl (string pkl_uuid, bool interop, XMLMetadata const & metadata, shared_ptr<const Signer> signer) const
+class AssetComparator
{
- assert (!_cpls.empty ());
+public:
+ bool operator() (shared_ptr<const Content> a, shared_ptr<const Content> b) {
+ return a->id() < b->id();
+ }
+};
+
+bool
+DCP::encrypted () const
+{
+ list<shared_ptr<CPL> > cpl = cpls ();
+ for (list<shared_ptr<CPL> >::const_iterator i = cpl.begin(); i != cpl.end(); ++i) {
+ if ((*i)->encrypted ()) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+void
+DCP::add (KDM const & kdm)
+{
+ list<KDMKey> keys = kdm.keys ();
+ list<shared_ptr<CPL> > cpl = cpls ();
- boost::filesystem::path p;
- p /= _directory;
+ for (list<shared_ptr<CPL> >::iterator i = cpl.begin(); i != cpl.end(); ++i) {
+ for (list<KDMKey>::iterator j = keys.begin(); j != keys.end(); ++j) {
+ if (j->cpl_id() == (*i)->id()) {
+ (*i)->add (kdm);
+ }
+ }
+ }
+}
+
+boost::filesystem::path
+DCP::write_pkl (Standard standard, string pkl_uuid, XMLMetadata metadata, shared_ptr<const Signer> signer) const
+{
+ boost::filesystem::path p = _directory;
stringstream s;
s << pkl_uuid << "_pkl.xml";
p /= s.str();
xmlpp::Document doc;
xmlpp::Element* pkl;
- if (interop) {
+ if (standard == INTEROP) {
pkl = doc.create_root_node("PackingList", "http://www.digicine.com/PROTO-ASDCP-PKL-20040311#");
} else {
pkl = doc.create_root_node("PackingList", "http://www.smpte-ra.org/schemas/429-8/2007/PKL");
@@ -101,36 +226,49 @@ DCP::write_pkl (string pkl_uuid, bool interop, XMLMetadata const & metadata, sha
}
pkl->add_child("Id")->add_child_text ("urn:uuid:" + pkl_uuid);
+
/* XXX: this is a bit of a hack */
- pkl->add_child("AnnotationText")->add_child_text(_cpls.front()->name());
+ list<shared_ptr<Asset> >::const_iterator i = _assets.begin();
+ shared_ptr<CPL> first_cpl;
+ while (i != _assets.end()) {
+ first_cpl = dynamic_pointer_cast<CPL> (*i);
+ if (first_cpl) {
+ break;
+ }
+ }
+
+ assert (first_cpl);
+ pkl->add_child("AnnotationText")->add_child_text (first_cpl->annotation_text ());
+
pkl->add_child("IssueDate")->add_child_text (metadata.issue_date);
pkl->add_child("Issuer")->add_child_text (metadata.issuer);
pkl->add_child("Creator")->add_child_text (metadata.creator);
xmlpp::Element* asset_list = pkl->add_child("AssetList");
- list<shared_ptr<const Content> > a = assets ();
- for (list<shared_ptr<const Content> >::const_iterator i = a.begin(); i != a.end(); ++i) {
- (*i)->write_to_pkl (asset_list);
- }
-
- for (list<shared_ptr<CPL> >::const_iterator i = _cpls.begin(); i != _cpls.end(); ++i) {
- (*i)->write_to_pkl (asset_list);
+
+ for (list<shared_ptr<Asset> >::const_iterator i = _assets.begin(); i != _assets.end(); ++i) {
+ shared_ptr<Content> c = dynamic_pointer_cast<Content> (*i);
+ if (c) {
+ c->write_to_pkl (asset_list);
+ }
}
if (signer) {
- signer->sign (pkl, interop);
+ signer->sign (pkl, standard);
}
doc.write_to_file (p.string (), "UTF-8");
return p.string ();
}
+/** Write the VOLINDEX file.
+ * @param standard DCP standard to use (INTEROP or SMPTE)
+ */
void
-DCP::write_volindex (bool interop) const
+DCP::write_volindex (Standard standard) const
{
- boost::filesystem::path p;
- p /= _directory;
- if (interop) {
+ boost::filesystem::path p = _directory;
+ if (standard == INTEROP) {
p /= "VOLINDEX";
} else {
p /= "VOLINDEX.xml";
@@ -143,11 +281,10 @@ DCP::write_volindex (bool interop) const
}
void
-DCP::write_assetmap (string pkl_uuid, int pkl_length, bool interop, XMLMetadata const & metadata) const
+DCP::write_assetmap (Standard standard, string pkl_uuid, int pkl_length, XMLMetadata metadata) const
{
- boost::filesystem::path p;
- p /= _directory;
- if (interop) {
+ boost::filesystem::path p = _directory;
+ if (standard == INTEROP) {
p /= "ASSETMAP";
} else {
p /= "ASSETMAP.xml";
@@ -155,7 +292,7 @@ DCP::write_assetmap (string pkl_uuid, int pkl_length, bool interop, XMLMetadata
xmlpp::Document doc;
xmlpp::Element* root;
- if (interop) {
+ if (standard == INTEROP) {
root = doc.create_root_node ("AssetMap", "http://www.digicine.com/PROTO-ASDCP-AM-20040311#");
} else {
root = doc.create_root_node ("AssetMap", "http://www.smpte-ra.org/schemas/429-9/2007/AM");
@@ -163,7 +300,7 @@ DCP::write_assetmap (string pkl_uuid, int pkl_length, bool interop, XMLMetadata
root->add_child("Id")->add_child_text ("urn:uuid:" + make_uuid());
root->add_child("AnnotationText")->add_child_text ("Created by " + metadata.creator);
- if (interop) {
+ if (standard == INTEROP) {
root->add_child("VolumeCount")->add_child_text ("1");
root->add_child("IssueDate")->add_child_text (metadata.issue_date);
root->add_child("Issuer")->add_child_text (metadata.issuer);
@@ -187,12 +324,7 @@ DCP::write_assetmap (string pkl_uuid, int pkl_length, bool interop, XMLMetadata
chunk->add_child("Offset")->add_child_text ("0");
chunk->add_child("Length")->add_child_text (lexical_cast<string> (pkl_length));
- for (list<shared_ptr<CPL> >::const_iterator i = _cpls.begin(); i != _cpls.end(); ++i) {
- (*i)->write_to_assetmap (asset_list);
- }
-
- list<shared_ptr<const Content> > a = assets ();
- for (list<shared_ptr<const Content> >::const_iterator i = a.begin(); i != a.end(); ++i) {
+ for (list<shared_ptr<Asset> >::const_iterator i = _assets.begin(); i != _assets.end(); ++i) {
(*i)->write_to_assetmap (asset_list);
}
@@ -201,173 +333,39 @@ DCP::write_assetmap (string pkl_uuid, int pkl_length, bool interop, XMLMetadata
}
void
-DCP::read (bool require_mxfs)
+DCP::write_xml (
+ Standard standard,
+ XMLMetadata metadata,
+ shared_ptr<const Signer> signer
+ )
{
- read_assets ();
- read_cpls (require_mxfs);
-}
-
-void
-DCP::read_assets ()
-{
- shared_ptr<parse::AssetMap> asset_map;
- try {
- boost::filesystem::path p = _directory;
- p /= "ASSETMAP";
- if (boost::filesystem::exists (p)) {
- asset_map.reset (new dcp::parse::AssetMap (p.string ()));
- } else {
- p = _directory;
- p /= "ASSETMAP.xml";
- if (boost::filesystem::exists (p)) {
- asset_map.reset (new dcp::parse::AssetMap (p.string ()));
- } else {
- boost::throw_exception (DCPReadError ("could not find AssetMap file"));
- }
- }
-
- } catch (FileError& e) {
- boost::throw_exception (FileError ("could not load AssetMap file", _files.asset_map, e.number ()));
- }
-
- for (list<shared_ptr<dcp::parse::AssetMapAsset> >::const_iterator i = asset_map->assets.begin(); i != asset_map->assets.end(); ++i) {
- if ((*i)->chunks.size() != 1) {
- boost::throw_exception (XMLError ("unsupported asset chunk count"));
- }
-
- boost::filesystem::path t = _directory;
- t /= (*i)->chunks.front()->path;
-
- if (boost::algorithm::ends_with (t.string(), ".mxf") || boost::algorithm::ends_with (t.string(), ".ttf")) {
- continue;
- }
-
- xmlpp::DomParser* p = new xmlpp::DomParser;
- try {
- p->parse_file (t.string());
- } catch (std::exception& e) {
- delete p;
- continue;
- }
-
- string const root = p->get_document()->get_root_node()->get_name ();
- delete p;
-
- if (root == "CompositionPlaylist") {
- _files.cpls.push_back (t.string());
- } else if (root == "PackingList") {
- if (_files.pkl.empty ()) {
- _files.pkl = t.string();
- } else {
- boost::throw_exception (DCPReadError ("duplicate PKLs found"));
- }
- }
- }
+ string const pkl_uuid = make_uuid ();
+ boost::filesystem::path const pkl_path = write_pkl (standard, pkl_uuid, metadata, signer);
- if (_files.cpls.empty ()) {
- boost::throw_exception (DCPReadError ("no CPL files found"));
- }
-
- if (_files.pkl.empty ()) {
- boost::throw_exception (DCPReadError ("no PKL file found"));
- }
-
- shared_ptr<parse::PKL> pkl;
- try {
- pkl.reset (new parse::PKL (_files.pkl));
- } catch (FileError& e) {
- boost::throw_exception (FileError ("could not load PKL file", _files.pkl, e.number ()));
- }
-
- _asset_maps.push_back (make_pair (boost::filesystem::absolute (_directory).string(), asset_map));
-}
-
-void
-DCP::read_cpls (bool require_mxfs)
-{
- for (list<string>::iterator i = _files.cpls.begin(); i != _files.cpls.end(); ++i) {
- _cpls.push_back (shared_ptr<CPL> (new CPL (_directory, *i, _asset_maps, require_mxfs)));
- }
-}
-
-bool
-DCP::equals (DCP const & other, EqualityOptions opt, boost::function<void (NoteType, string)> note) const
-{
- if (_cpls.size() != other._cpls.size()) {
- note (ERROR, "CPL counts differ");
- return false;
- }
-
- list<shared_ptr<CPL> >::const_iterator a = _cpls.begin ();
- list<shared_ptr<CPL> >::const_iterator b = other._cpls.begin ();
-
- while (a != _cpls.end ()) {
- if (!(*a)->equals (*b->get(), opt, note)) {
- return false;
+ write_volindex (standard);
+ write_assetmap (standard, pkl_uuid, boost::filesystem::file_size (pkl_path), metadata);
+
+ for (list<shared_ptr<Asset> >::const_iterator i = _assets.begin(); i != _assets.end(); ++i) {
+ shared_ptr<CPL> c = dynamic_pointer_cast<CPL> (*i);
+ if (c) {
+ string const filename = c->id() + "_cpl.xml";
+ c->write_xml (_directory / filename, standard, metadata, signer);
}
- ++a;
- ++b;
- }
-
- return true;
-}
-
-void
-DCP::add_cpl (shared_ptr<CPL> cpl)
-{
- _cpls.push_back (cpl);
-}
-
-class AssetComparator
-{
-public:
- bool operator() (shared_ptr<const Content> a, shared_ptr<const Content> b) {
- return a->id() < b->id();
- }
-};
-
-list<shared_ptr<const Content> >
-DCP::assets () const
-{
- list<shared_ptr<const Content> > a;
- for (list<shared_ptr<CPL> >::const_iterator i = _cpls.begin(); i != _cpls.end(); ++i) {
- list<shared_ptr<const Content> > t = (*i)->assets ();
- a.merge (t);
}
-
- a.sort (AssetComparator ());
- a.unique ();
- return a;
}
-bool
-DCP::encrypted () const
+list<shared_ptr<CPL> >
+DCP::cpls () const
{
- for (list<shared_ptr<CPL> >::const_iterator i = _cpls.begin(); i != _cpls.end(); ++i) {
- if ((*i)->encrypted ()) {
- return true;
+ list<shared_ptr<CPL> > cpls;
+ for (list<shared_ptr<Asset> >::const_iterator i = _assets.begin(); i != _assets.end(); ++i) {
+ shared_ptr<CPL> c = dynamic_pointer_cast<CPL> (*i);
+ if (c) {
+ cpls.push_back (c);
}
}
- return false;
+ return cpls;
}
-void
-DCP::add_kdm (KDM const & kdm)
-{
- list<KDMKey> keys = kdm.keys ();
- for (list<shared_ptr<CPL> >::iterator i = _cpls.begin(); i != _cpls.end(); ++i) {
- for (list<KDMKey>::iterator j = keys.begin(); j != keys.end(); ++j) {
- if (j->cpl_id() == (*i)->id()) {
- (*i)->add_kdm (kdm);
- }
- }
- }
-}
-
-void
-DCP::add_assets_from (DCP const & ov)
-{
- copy (ov._asset_maps.begin(), ov._asset_maps.end(), back_inserter (_asset_maps));
-}
diff --git a/src/dcp.h b/src/dcp.h
index 19903d3f..9f6d60fd 100644
--- a/src/dcp.h
+++ b/src/dcp.h
@@ -24,12 +24,13 @@
#ifndef LIBDCP_DCP_H
#define LIBDCP_DCP_H
-#include <string>
-#include <vector>
-#include <boost/shared_ptr.hpp>
-#include <boost/signals2.hpp>
#include "types.h"
#include "certificates.h"
+#include "metadata.h"
+#include <boost/shared_ptr.hpp>
+#include <boost/signals2.hpp>
+#include <string>
+#include <vector>
namespace xmlpp {
class Document;
@@ -41,14 +42,12 @@ namespace dcp
{
class Content;
-class PictureAsset;
-class SoundAsset;
-class SubtitleAsset;
class Reel;
class CPL;
class XMLMetadata;
class Signer;
class KDM;
+class Asset;
namespace parse {
class AssetMap;
@@ -69,21 +68,7 @@ public:
*/
DCP (boost::filesystem::path directory);
- void read (bool require_mxfs = true);
-
- /** Read an existing DCP's assets.
- *
- * The DCP's XML metadata will be examined, and you can then look at the contents
- * of the DCP.
- */
- void read_assets ();
-
- void read_cpls (bool require_mxfs = true);
-
- /** Write the required XML files to the directory that was
- * passed into the constructor.
- */
- void write_xml (bool interop, XMLMetadata const &, boost::shared_ptr<const Signer> signer = boost::shared_ptr<const Signer> ()) const;
+ void read ();
/** Compare this DCP with another, according to various options.
* @param other DCP to compare this one to.
@@ -92,29 +77,19 @@ public:
*/
bool equals (DCP const & other, EqualityOptions options, boost::function<void (NoteType, std::string)> note) const;
- /** Add a CPL to this DCP.
- * @param cpl CPL to add.
- */
- void add_cpl (boost::shared_ptr<CPL> cpl);
-
- /** @return The list of CPLs in this DCP */
- std::list<boost::shared_ptr<CPL> > cpls () const {
- return _cpls;
- }
+ void add (boost::shared_ptr<Asset> asset);
- /** Add another DCP as a source of assets for this DCP. This should be called before
- * ::read() on the DCP that needs the extra assets. For example
- *
- * DCP original_version ("my_dcp_OV");
- * DCP supplemental ("my_dcp_VF");
- * supplemental.add_assets_from (original_version);
- * supplemental.read ();
- */
- void add_assets_from (DCP const &);
+ std::list<boost::shared_ptr<CPL> > cpls () const;
bool encrypted () const;
- void add_kdm (KDM const &);
+ void add (KDM const &);
+
+ void write_xml (
+ Standard standard,
+ XMLMetadata metadata = XMLMetadata (),
+ boost::shared_ptr<const Signer> signer = boost::shared_ptr<const Signer> ()
+ );
/** Emitted with a parameter between 0 and 1 to indicate progress
* for long jobs.
@@ -126,34 +101,19 @@ private:
/** Write the PKL file.
* @param pkl_uuid UUID to use.
*/
- std::string write_pkl (std::string pkl_uuid, bool, XMLMetadata const &, boost::shared_ptr<const Signer>) const;
+ boost::filesystem::path write_pkl (Standard standard, std::string pkl_uuid, XMLMetadata metadata, boost::shared_ptr<const Signer> signer) const;
- /** Write the VOLINDEX file */
- void write_volindex (bool) const;
+ void write_volindex (Standard standard) const;
/** Write the ASSETMAP file.
* @param pkl_uuid UUID of our PKL.
* @param pkl_length Length of our PKL in bytes.
*/
- void write_assetmap (std::string pkl_uuid, int pkl_length, bool, XMLMetadata const &) const;
-
- /** @return Assets in all the CPLs in this DCP */
- std::list<boost::shared_ptr<const Content> > assets () const;
-
- struct Files {
- std::list<std::string> cpls;
- std::string pkl;
- std::string asset_map;
- };
-
- Files _files;
+ void write_assetmap (Standard standard, std::string pkl_uuid, int pkl_length, XMLMetadata metadata) const;
/** the directory that we are writing to */
boost::filesystem::path _directory;
- /** our CPLs */
- std::list<boost::shared_ptr<CPL> > _cpls;
-
- std::list<PathAssetMap> _asset_maps;
+ std::list<boost::shared_ptr<Asset> > _assets;
};
}
diff --git a/src/exceptions.cc b/src/exceptions.cc
index c3755a60..e5a46948 100644
--- a/src/exceptions.cc
+++ b/src/exceptions.cc
@@ -17,13 +17,17 @@
*/
+/** @file src/exceptions.cc
+ * @brief Exceptions thrown by libdcp.
+ */
+
#include "exceptions.h"
#include "compose.hpp"
using std::string;
using namespace dcp;
-FileError::FileError (std::string const & message, boost::filesystem::path filename, int number)
+FileError::FileError (string message, boost::filesystem::path filename, int number)
: _message (String::compose ("%1 (error %2) (%3)", message, filename.string(), number))
, _filename (filename)
, _number (number)
@@ -31,3 +35,9 @@ FileError::FileError (std::string const & message, boost::filesystem::path filen
}
+UnresolvedRefError::UnresolvedRefError (string id)
+ : _message (String::compose ("Unresolved reference to asset id %1", id))
+{
+
+}
+
diff --git a/src/exceptions.h b/src/exceptions.h
index 2a7fbdda..c1d47e51 100644
--- a/src/exceptions.h
+++ b/src/exceptions.h
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2012 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -33,7 +33,7 @@ namespace dcp
class FileError : public std::exception
{
public:
- FileError (std::string const & message, boost::filesystem::path filename, int number);
+ FileError (std::string message, boost::filesystem::path filename, int number);
~FileError () throw () {}
/** @return error message */
@@ -63,7 +63,7 @@ private:
class MXFFileError : public FileError
{
public:
- MXFFileError (std::string const & message, boost::filesystem::path filename, int number)
+ MXFFileError (std::string message, boost::filesystem::path filename, int number)
: FileError (message, filename, number)
{}
};
@@ -72,7 +72,7 @@ public:
class MiscError : public std::exception
{
public:
- MiscError (std::string const & message) : _message (message) {}
+ MiscError (std::string message) : _message (message) {}
~MiscError () throw () {}
/** @return error message */
@@ -89,7 +89,7 @@ private:
class DCPReadError : public std::exception
{
public:
- DCPReadError (std::string const & message) : _message (message) {}
+ DCPReadError (std::string message) : _message (message) {}
~DCPReadError () throw () {}
/** @return error message */
@@ -106,7 +106,7 @@ private:
class XMLError : public std::exception
{
public:
- XMLError (std::string const & message) : _message (message) {}
+ XMLError (std::string message) : _message (message) {}
~XMLError () throw () {}
/** @return error message */
@@ -118,6 +118,21 @@ private:
/** error message */
std::string _message;
};
+
+class UnresolvedRefError : public std::exception
+{
+public:
+ UnresolvedRefError (std::string id);
+ ~UnresolvedRefError () throw () {}
+
+ /** @return error message */
+ char const * what () const throw () {
+ return _message.c_str ();
+ }
+
+private:
+ std::string _message;
+};
}
diff --git a/src/file.cc b/src/file.cc
new file mode 100644
index 00000000..d39f93e0
--- /dev/null
+++ b/src/file.cc
@@ -0,0 +1,38 @@
+/*
+ Copyright (C) 2014 Carl Hetherington <cth@carlh.net>
+
+ This program 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.
+
+ This program 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 this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#include "file.h"
+#include "util.h"
+
+using namespace dcp;
+
+File::File (boost::filesystem::path file)
+{
+ _size = boost::filesystem::file_size (file);
+ _data = new uint8_t[_size];
+ FILE* f = dcp::fopen_boost (file, "r");
+ assert (f);
+ fread (_data, 1, _size, f);
+ fclose (f);
+}
+
+File::~File ()
+{
+ delete[] _data;
+}
diff --git a/src/file.h b/src/file.h
new file mode 100644
index 00000000..f2b99209
--- /dev/null
+++ b/src/file.h
@@ -0,0 +1,43 @@
+/*
+ Copyright (C) 2014 Carl Hetherington <cth@carlh.net>
+
+ This program 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.
+
+ This program 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 this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#include <boost/filesystem.hpp>
+
+namespace dcp {
+
+class File
+{
+public:
+ File (boost::filesystem::path file);
+ ~File ();
+
+ uint8_t* data () const {
+ return _data;
+ }
+
+ int64_t size () const {
+ return _size;
+ }
+
+private:
+ uint8_t* _data;
+ int64_t _size;
+};
+
+}
diff --git a/src/parse/subtitle.cc b/src/font.cc
index 3f9869b4..5a568a63 100644
--- a/src/parse/subtitle.cc
+++ b/src/font.cc
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2012-2013 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -17,18 +17,16 @@
*/
-#include <boost/shared_ptr.hpp>
-#include <boost/optional.hpp>
-#include "subtitle.h"
-#include "../types.h"
+#include "font.h"
+#include "xml.h"
+#include "text.h"
+#include <libcxml/cxml.h>
using std::string;
using std::list;
using boost::shared_ptr;
using boost::optional;
-using boost::lexical_cast;
using namespace dcp;
-using namespace dcp::parse;
Font::Font (shared_ptr<const cxml::Node> node)
{
@@ -81,55 +79,3 @@ Font::Font (list<shared_ptr<Font> > const & font_nodes)
}
}
}
-
-LoadFont::LoadFont (shared_ptr<const cxml::Node> node)
-{
- id = node->string_attribute ("Id");
- uri = node->string_attribute ("URI");
-}
-
-
-Subtitle::Subtitle (shared_ptr<const cxml::Node> node)
-{
- in = Time (node->string_attribute ("TimeIn"));
- out = Time (node->string_attribute ("TimeOut"));
- font_nodes = type_children<Font> (node, "Font");
- text_nodes = type_children<Text> (node, "Text");
- fade_up_time = fade_time (node, "FadeUpTime");
- fade_down_time = fade_time (node, "FadeDownTime");
-}
-
-Time
-Subtitle::fade_time (shared_ptr<const cxml::Node> node, string name)
-{
- string const u = node->optional_string_attribute (name).get_value_or ("");
- Time t;
-
- if (u.empty ()) {
- t = Time (0, 0, 0, 20);
- } else if (u.find (":") != string::npos) {
- t = Time (u);
- } else {
- t = Time (0, 0, 0, lexical_cast<int> (u));
- }
-
- if (t > Time (0, 0, 8, 0)) {
- t = Time (0, 0, 8, 0);
- }
-
- return t;
-}
-
-Text::Text (shared_ptr<const cxml::Node> node)
- : v_align (CENTER)
-{
- text = node->content ();
- v_position = node->number_attribute<float> ("VPosition");
- optional<string> v = node->optional_string_attribute ("VAlign");
- if (v) {
- v_align = string_to_valign (v.get ());
- }
-
- font_nodes = type_children<Font> (node, "Font");
-}
-
diff --git a/src/parse/subtitle.h b/src/font.h
index 50c2ebc5..1b29e570 100644
--- a/src/parse/subtitle.h
+++ b/src/font.h
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2012 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -17,51 +17,18 @@
*/
-#include "../xml.h"
-#include "../dcp_time.h"
-#include "../types.h"
+#include "types.h"
+#include "subtitle.h"
+#include <boost/shared_ptr.hpp>
+#include <boost/optional.hpp>
+#include <list>
-namespace dcp
-{
-
-namespace parse
-{
-
-class Font;
+namespace cxml {
+ class Node;
+}
-class Text
-{
-public:
- Text ()
- : v_position (0)
- , v_align (TOP)
- {}
+namespace dcp {
- Text (boost::shared_ptr<const cxml::Node> node);
-
- float v_position;
- VAlign v_align;
- std::string text;
- std::list<boost::shared_ptr<Font> > font_nodes;
-};
-
-class Subtitle
-{
-public:
- Subtitle () {}
- Subtitle (boost::shared_ptr<const cxml::Node> node);
-
- Time in;
- Time out;
- Time fade_up_time;
- Time fade_down_time;
- std::list<boost::shared_ptr<Font> > font_nodes;
- std::list<boost::shared_ptr<Text> > text_nodes;
-
-private:
- Time fade_time (boost::shared_ptr<const cxml::Node>, std::string name);
-};
-
class Font
{
public:
@@ -85,16 +52,4 @@ public:
std::list<boost::shared_ptr<Text> > text_nodes;
};
-class LoadFont
-{
-public:
- LoadFont () {}
- LoadFont (boost::shared_ptr<const cxml::Node> node);
-
- std::string id;
- std::string uri;
-};
-
-}
-
}
diff --git a/src/gamma_lut.cc b/src/gamma_lut.cc
index 0b8ad2fd..1a954914 100644
--- a/src/gamma_lut.cc
+++ b/src/gamma_lut.cc
@@ -17,18 +17,18 @@
*/
-#include <cmath>
#include "gamma_lut.h"
#include "lut_cache.h"
+#include <cmath>
using namespace dcp;
LUTCache<GammaLUT> GammaLUT::cache;
-GammaLUT::GammaLUT(int bits, float gamma)
+GammaLUT::GammaLUT (int bits, float gamma)
: LUT (bits, gamma)
{
- int const bit_length = pow(2, bits);
+ int const bit_length = pow (2, bits);
for (int i = 0; i < bit_length; ++i) {
_lut[i] = pow(float(i) / (bit_length - 1), gamma);
}
diff --git a/src/gamma_lut.h b/src/gamma_lut.h
index 095ad882..31615afd 100644
--- a/src/gamma_lut.h
+++ b/src/gamma_lut.h
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2012-2013 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/src/kdm.cc b/src/kdm.cc
index bdfa1fec..92e9a756 100644
--- a/src/kdm.cc
+++ b/src/kdm.cc
@@ -108,7 +108,7 @@ KDM::KDM (
apu.recipient.x509_subject_name = recipient_cert->subject ();
apu.composition_playlist_id = "urn:uuid:" + cpl->id ();
// apu.content_authenticator = signer->certificates().leaf()->thumbprint ();
- apu.content_title_text = cpl->name ();
+ apu.content_title_text = cpl->content_title_text ();
apu.content_keys_not_valid_before = ptime_to_string (not_valid_before);
apu.content_keys_not_valid_after = ptime_to_string (not_valid_after);
apu.authorized_device_info.device_list_identifier = "urn:uuid:" + make_uuid ();
diff --git a/src/key.h b/src/key.h
index be9f95f4..d6b2f2f2 100644
--- a/src/key.h
+++ b/src/key.h
@@ -25,6 +25,7 @@
#define LIBDCP_KEY_H
#include <stdint.h>
+#include <string>
namespace dcp {
diff --git a/src/load_font.cc b/src/load_font.cc
new file mode 100644
index 00000000..a337856c
--- /dev/null
+++ b/src/load_font.cc
@@ -0,0 +1,30 @@
+/*
+ Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
+
+ This program 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.
+
+ This program 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 this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#include "load_font.h"
+#include <libcxml/cxml.h>
+
+using boost::shared_ptr;
+using namespace dcp;
+
+LoadFont::LoadFont (shared_ptr<const cxml::Node> node)
+{
+ id = node->string_attribute ("Id");
+ uri = node->string_attribute ("URI");
+}
diff --git a/src/load_font.h b/src/load_font.h
new file mode 100644
index 00000000..6319b1de
--- /dev/null
+++ b/src/load_font.h
@@ -0,0 +1,38 @@
+/*
+ Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
+
+ This program 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.
+
+ This program 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 this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#include <boost/shared_ptr.hpp>
+
+namespace cxml {
+ class Node;
+}
+
+namespace dcp {
+
+class LoadFont
+{
+public:
+ LoadFont () {}
+ LoadFont (boost::shared_ptr<const cxml::Node> node);
+
+ std::string id;
+ std::string uri;
+};
+
+}
diff --git a/src/mono_picture_mxf.cc b/src/mono_picture_mxf.cc
index cea21c15..e33454dc 100644
--- a/src/mono_picture_mxf.cc
+++ b/src/mono_picture_mxf.cc
@@ -45,14 +45,10 @@ MonoPictureMXF::MonoPictureMXF (boost::filesystem::path file)
boost::throw_exception (DCPReadError ("could not read video MXF information"));
}
- _size.width = desc.StoredWidth;
- _size.height = desc.StoredHeight;
- _edit_rate = desc.EditRate.Numerator;
- assert (desc.EditRate.Denominator == 1);
- _intrinsic_duration = desc.ContainerDuration;
+ read_picture_descriptor (desc);
}
-MonoPictureMXF::MonoPictureMXF (int edit_rate)
+MonoPictureMXF::MonoPictureMXF (Fraction edit_rate)
: PictureMXF (edit_rate)
{
@@ -121,10 +117,10 @@ MonoPictureMXF::equals (shared_ptr<const Content> other, EqualityOptions opt, bo
}
shared_ptr<PictureMXFWriter>
-MonoPictureMXF::start_write (boost::filesystem::path file, bool overwrite)
+MonoPictureMXF::start_write (boost::filesystem::path file, Standard standard, bool overwrite)
{
/* XXX: can't we use shared_ptr here? */
- return shared_ptr<MonoPictureMXFWriter> (new MonoPictureMXFWriter (this, file, overwrite));
+ return shared_ptr<MonoPictureMXFWriter> (new MonoPictureMXFWriter (this, file, standard, overwrite));
}
string
diff --git a/src/mono_picture_mxf.h b/src/mono_picture_mxf.h
index 8c8ee531..9f0a2eea 100644
--- a/src/mono_picture_mxf.h
+++ b/src/mono_picture_mxf.h
@@ -24,6 +24,8 @@
namespace dcp {
+class MonoPictureMXFWriter;
+
/** @class MonoPictureMXF
* @brief A 2D (monoscopic) picture MXF.
*/
@@ -38,10 +40,10 @@ public:
/** Create a MonoPictureMXF with a given edit rate.
* @param edit_rate Edit rate (i.e. frame rate) in frames per second.
*/
- MonoPictureMXF (int edit_rate);
+ MonoPictureMXF (Fraction edit_rate);
/** Start a progressive write to a MonoPictureMXF */
- boost::shared_ptr<PictureMXFWriter> start_write (boost::filesystem::path, bool);
+ boost::shared_ptr<PictureMXFWriter> start_write (boost::filesystem::path, Standard standard, bool);
boost::shared_ptr<const MonoPictureFrame> get_frame (int n) const;
bool equals (boost::shared_ptr<const Content> other, EqualityOptions opt, boost::function<void (NoteType, std::string)> note) const;
diff --git a/src/mono_picture_mxf_writer.cc b/src/mono_picture_mxf_writer.cc
index 590a3f7d..619d298e 100644
--- a/src/mono_picture_mxf_writer.cc
+++ b/src/mono_picture_mxf_writer.cc
@@ -40,8 +40,8 @@ struct MonoPictureMXFWriter::ASDCPState : public ASDCPStateBase
/** @param a Asset to write to. `a' must not be deleted while
* this writer class still exists, or bad things will happen.
*/
-MonoPictureMXFWriter::MonoPictureMXFWriter (PictureMXF* asset, boost::filesystem::path file, bool overwrite)
- : PictureMXFWriter (asset, file, overwrite)
+MonoPictureMXFWriter::MonoPictureMXFWriter (PictureMXF* asset, boost::filesystem::path file, Standard standard, bool overwrite)
+ : PictureMXFWriter (asset, file, standard, overwrite)
, _state (new MonoPictureMXFWriter::ASDCPState)
{
_state->encryption_context = asset->encryption_context ();
@@ -50,7 +50,7 @@ MonoPictureMXFWriter::MonoPictureMXFWriter (PictureMXF* asset, boost::filesystem
void
MonoPictureMXFWriter::start (uint8_t* data, int size)
{
- dcp::start (this, _state, _mxf, data, size);
+ dcp::start (this, _state, _standard, _picture_mxf, data, size);
}
FrameInfo
@@ -95,15 +95,11 @@ MonoPictureMXFWriter::fake_write (int size)
void
MonoPictureMXFWriter::finalize ()
{
- assert (!_finalized);
-
Kumu::Result_t r = _state->mxf_writer.Finalize();
if (ASDCP_FAILURE (r)) {
boost::throw_exception (MXFFileError ("error in finalizing video MXF", _mxf->file().string(), r));
}
- _finalized = true;
- _mxf->set_intrinsic_duration (_frames_written);
- _mxf->set_duration (_frames_written);
+ PictureMXFWriter::finalize ();
}
diff --git a/src/mono_picture_mxf_writer.h b/src/mono_picture_mxf_writer.h
index c4d9b6ed..7ff87a5d 100644
--- a/src/mono_picture_mxf_writer.h
+++ b/src/mono_picture_mxf_writer.h
@@ -45,7 +45,7 @@ public:
private:
friend class MonoPictureMXF;
- MonoPictureMXFWriter (PictureMXF *, boost::filesystem::path file, bool);
+ MonoPictureMXFWriter (PictureMXF *, boost::filesystem::path file, Standard standard, bool);
void start (uint8_t *, int);
/* do this with an opaque pointer so we don't have to include
diff --git a/src/mxf.cc b/src/mxf.cc
index fa3aed8b..42d92536 100644
--- a/src/mxf.cc
+++ b/src/mxf.cc
@@ -21,10 +21,6 @@
* @brief Parent class for assets of DCPs made up of MXF files.
*/
-#include <iostream>
-#include <boost/filesystem.hpp>
-#include <boost/lexical_cast.hpp>
-#include <libxml++/nodes/element.h>
#include "AS_DCP.h"
#include "KM_prng.h"
#include "KM_util.h"
@@ -33,6 +29,10 @@
#include "metadata.h"
#include "exceptions.h"
#include "kdm.h"
+#include <libxml++/nodes/element.h>
+#include <boost/filesystem.hpp>
+#include <boost/lexical_cast.hpp>
+#include <iostream>
using std::string;
using std::list;
@@ -42,12 +42,20 @@ using boost::lexical_cast;
using boost::dynamic_pointer_cast;
using namespace dcp;
+MXF::MXF (Fraction edit_rate)
+ : Content (edit_rate)
+ , _progress (0)
+ , _encryption_context (0)
+ , _decryption_context (0)
+{
+
+}
+
MXF::MXF (boost::filesystem::path file)
: Content (file)
, _progress (0)
, _encryption_context (0)
, _decryption_context (0)
- , _interop (false)
{
}
@@ -59,13 +67,13 @@ MXF::~MXF ()
}
void
-MXF::fill_writer_info (ASDCP::WriterInfo* writer_info)
+MXF::fill_writer_info (ASDCP::WriterInfo* writer_info, Standard standard)
{
writer_info->ProductVersion = _metadata.product_version;
writer_info->CompanyName = _metadata.company_name;
writer_info->ProductName = _metadata.product_name.c_str();
- if (_interop) {
+ if (standard == INTEROP) {
writer_info->LabelSetType = ASDCP::LS_MXF_INTEROP;
} else {
writer_info->LabelSetType = ASDCP::LS_MXF_SMPTE;
@@ -108,25 +116,6 @@ MXF::equals (shared_ptr<const Content> other, EqualityOptions opt, boost::functi
}
void
-MXF::write_to_cpl (xmlpp::Element* node) const
-{
- pair<string, string> const attr = cpl_node_attribute ();
- xmlpp::Element* a = node->add_child (cpl_node_name ());
- if (!attr.first.empty ()) {
- a->set_attribute (attr.first, attr.second);
- }
- a->add_child ("Id")->add_child_text ("urn:uuid:" + _id);
- a->add_child ("AnnotationText")->add_child_text (_file.string ());
- a->add_child ("EditRate")->add_child_text (lexical_cast<string> (_edit_rate) + " 1");
- a->add_child ("IntrinsicDuration")->add_child_text (lexical_cast<string> (_intrinsic_duration));
- a->add_child ("EntryPoint")->add_child_text (lexical_cast<string> (_entry_point));
- a->add_child ("Duration")->add_child_text (lexical_cast<string> (_duration));
- if (!_key_id.empty ()) {
- a->add_child("KeyId")->add_child_text ("urn:uuid:" + _key_id);
- }
-}
-
-void
MXF::set_key (Key key)
{
_key = key;
diff --git a/src/mxf.h b/src/mxf.h
index a83d9fff..3aaadfd7 100644
--- a/src/mxf.h
+++ b/src/mxf.h
@@ -20,10 +20,10 @@
#ifndef LIBDCP_MXF_ASSET_H
#define LIBDCP_MXF_ASSET_H
-#include <boost/signals2.hpp>
#include "content.h"
#include "key.h"
#include "metadata.h"
+#include <boost/signals2.hpp>
namespace ASDCP {
class AESEncContext;
@@ -41,19 +41,23 @@ class MXFMetadata;
class MXF : public Content
{
public:
+ MXF (Fraction edit_rate);
MXF (boost::filesystem::path file);
- MXF (int edit_rate);
~MXF ();
virtual bool equals (boost::shared_ptr<const Content> other, EqualityOptions opt, boost::function<void (NoteType, std::string)> note) const;
- virtual void write_to_cpl (xmlpp::Element *) const;
virtual std::string key_type () const = 0;
+
+ std::string pkl_type () const {
+ return "application/x-smpte-mxf";
+ }
/** Fill in a ADSCP::WriteInfo struct.
* @param w struct to fill in.
+ * @param standard INTEROP or SMPTE.
*/
- void fill_writer_info (ASDCP::WriterInfo* w);
+ void fill_writer_info (ASDCP::WriterInfo* w, Standard standard);
void set_progress (boost::signals2::signal<void (float)>* progress) {
_progress = progress;
@@ -89,23 +93,7 @@ public:
return _metadata;
}
- /** Set whether or not the asset should be written in Interop mode.
- * @param i true to use interop.
- */
- void set_interop (bool i) {
- _interop = i;
- }
-
- bool interop () const {
- return _interop;
- }
-
protected:
- virtual std::string cpl_node_name () const = 0;
- virtual std::pair<std::string, std::string> cpl_node_attribute () const {
- return std::make_pair ("", "");
- }
-
/** Signal to emit to report progress, or 0 */
boost::signals2::signal<void (float)>* _progress;
ASDCP::AESEncContext* _encryption_context;
@@ -113,7 +101,6 @@ protected:
std::string _key_id;
boost::optional<Key> _key;
MXFMetadata _metadata;
- bool _interop;
};
}
diff --git a/src/mxf_writer.cc b/src/mxf_writer.cc
new file mode 100644
index 00000000..c5fca159
--- /dev/null
+++ b/src/mxf_writer.cc
@@ -0,0 +1,46 @@
+/*
+ Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
+
+ This program 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.
+
+ This program 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 this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#include "mxf_writer.h"
+#include "mxf.h"
+
+using namespace dcp;
+
+MXFWriter::MXFWriter (MXF* mxf, boost::filesystem::path file)
+ : _mxf (mxf)
+ , _file (file)
+ , _frames_written (0)
+ , _finalized (false)
+{
+ mxf->_file = file;
+ mxf->_hash.clear ();
+}
+
+MXFWriter::~MXFWriter ()
+{
+ assert (_finalized);
+}
+
+void
+MXFWriter::finalize ()
+{
+ assert (!_finalized);
+ _finalized = true;
+ _mxf->_intrinsic_duration = _frames_written;
+}
diff --git a/src/mxf_writer.h b/src/mxf_writer.h
new file mode 100644
index 00000000..19632131
--- /dev/null
+++ b/src/mxf_writer.h
@@ -0,0 +1,46 @@
+/*
+ Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
+
+ This program 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.
+
+ This program 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 this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#ifndef LIBDCP_MXF_WRITER_H
+#define LIBDCP_MXF_WRITER_H
+
+#include <boost/filesystem.hpp>
+
+namespace dcp {
+
+class MXF;
+
+class MXFWriter : public boost::noncopyable
+{
+public:
+ virtual ~MXFWriter ();
+ virtual void finalize ();
+
+protected:
+ MXFWriter (MXF* mxf, boost::filesystem::path file);
+
+ MXF* _mxf;
+ boost::filesystem::path _file;
+ int64_t _frames_written;
+ bool _finalized;
+};
+
+}
+
+#endif
diff --git a/src/object.cc b/src/object.cc
index e9a4f62b..e3849d79 100644
--- a/src/object.cc
+++ b/src/object.cc
@@ -23,12 +23,16 @@
using std::string;
using namespace dcp;
+/** Create an Object with a random ID. */
Object::Object ()
: _id (make_uuid ())
{
}
+/** Create an Object with a given ID.
+ * @param ID to use.
+ */
Object::Object (string id)
: _id (id)
{
diff --git a/src/object.h b/src/object.h
index 636c76a0..e12888e8 100644
--- a/src/object.h
+++ b/src/object.h
@@ -24,7 +24,9 @@
namespace dcp {
-/** Some part of a DCP that has a UUID */
+/** @class Object
+ * @brief Some part of a DCP that has a UUID.
+ */
class Object
{
public:
@@ -32,11 +34,13 @@ public:
Object (std::string id);
virtual ~Object () {}
+ /** @return ID */
std::string id () const {
return _id;
}
protected:
+ /** ID */
std::string _id;
};
diff --git a/src/parse/asset_map.cc b/src/parse/asset_map.cc
deleted file mode 100644
index 0b323fb3..00000000
--- a/src/parse/asset_map.cc
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- Copyright (C) 2012 Carl Hetherington <cth@carlh.net>
-
- This program 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.
-
- This program 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 this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-*/
-
-/** @file src/asset_map.cc
- * @brief Classes used to parse a AssetMap.
- */
-
-#include <boost/algorithm/string.hpp>
-#include "asset_map.h"
-#include "../util.h"
-#include "../xml.h"
-
-using std::string;
-using std::list;
-using boost::shared_ptr;
-using namespace dcp::parse;
-
-AssetMap::AssetMap (string file)
-{
- cxml::Document f ("AssetMap");
- f.read_file (file);
-
- id = f.string_child ("Id");
- creator = f.string_child ("Creator");
- volume_count = f.number_child<int64_t> ("VolumeCount");
- issue_date = f.string_child ("IssueDate");
- issuer = f.string_child ("Issuer");
- assets = type_grand_children<AssetMapAsset> (f, "AssetList", "Asset");
-}
-
-AssetMapAsset::AssetMapAsset (shared_ptr<const cxml::Node> node)
-{
- id = node->string_child ("Id");
- packing_list = node->optional_string_child ("PackingList").get_value_or ("");
- chunks = type_grand_children<Chunk> (node, "ChunkList", "Chunk");
-}
-
-Chunk::Chunk (shared_ptr<const cxml::Node> node)
-{
- path = node->string_child ("Path");
-
- string const prefix = "file://";
-
- if (boost::algorithm::starts_with (path, prefix)) {
- path = path.substr (prefix.length());
- }
-
- volume_index = node->optional_number_child<int64_t> ("VolumeIndex").get_value_or (0);
- offset = node->optional_number_child<int64_t> ("Offset").get_value_or (0);
- length = node->optional_number_child<int64_t> ("Length").get_value_or (0);
-}
-
-shared_ptr<AssetMapAsset>
-AssetMap::asset_from_id (string id) const
-{
- for (list<shared_ptr<AssetMapAsset> >::const_iterator i = assets.begin (); i != assets.end(); ++i) {
- if ((*i)->id == id) {
- return *i;
- }
- }
-
- return shared_ptr<AssetMapAsset> ();
-}
diff --git a/src/parse/asset_map.h b/src/parse/asset_map.h
deleted file mode 100644
index e3035593..00000000
--- a/src/parse/asset_map.h
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- Copyright (C) 2012 Carl Hetherington <cth@carlh.net>
-
- This program 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.
-
- This program 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 this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-*/
-
-/** @file src/asset_map.h
- * @brief Classes used to parse a AssetMap.
- */
-
-#include <stdint.h>
-#include <boost/shared_ptr.hpp>
-#include <libcxml/cxml.h>
-
-namespace dcp {
-
-namespace parse {
-
-/** @class Chunk
- * @brief A simple parser for and representation of a \<Chunk\> node within an asset map.
- */
-class Chunk
-{
-public:
- Chunk ();
- Chunk (boost::shared_ptr<const cxml::Node> node);
-
- std::string path;
- int64_t volume_index;
- int64_t offset;
- int64_t length;
-};
-
-/** @class AssetMapAsset
- * @brief A simple parser for and representation of an \<AssetMap\> node within an asset map.
- */
-class AssetMapAsset
-{
-public:
- AssetMapAsset ();
- AssetMapAsset (boost::shared_ptr<const cxml::Node> node);
-
- std::string id;
- std::string packing_list;
- std::list<boost::shared_ptr<Chunk> > chunks;
-};
-
-/** @class AssetMap
- * @brief A simple parser for and representation of an asset map file.
- */
-class AssetMap
-{
-public:
- AssetMap (std::string file);
-
- boost::shared_ptr<AssetMapAsset> asset_from_id (std::string id) const;
-
- std::string id;
- std::string creator;
- int64_t volume_count;
- std::string issue_date;
- std::string issuer;
- std::list<boost::shared_ptr<AssetMapAsset> > assets;
-};
-
-}
-
-}
diff --git a/src/parse/cpl.cc b/src/parse/cpl.cc
deleted file mode 100644
index d94fb68e..00000000
--- a/src/parse/cpl.cc
+++ /dev/null
@@ -1,151 +0,0 @@
-/*
- Copyright (C) 2012 Carl Hetherington <cth@carlh.net>
-
- This program 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.
-
- This program 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 this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-*/
-
-/** @file src/cpl_file.cc
- * @brief Classes used to parse a CPL.
- */
-
-#include <iostream>
-#include "cpl.h"
-#include "../xml.h"
-#include "../util.h"
-
-using std::string;
-using std::bad_cast;
-using boost::shared_ptr;
-using namespace dcp::parse;
-
-CPL::CPL (string file)
-{
- cxml::Document f ("CompositionPlaylist");
- f.read_file (file);
-
- id = f.string_child ("Id");
- annotation_text = f.optional_string_child ("AnnotationText").get_value_or ("");
- issue_date = f.string_child ("IssueDate");
- creator = f.optional_string_child ("Creator").get_value_or ("");
- content_title_text = f.string_child ("ContentTitleText");
- content_kind = content_kind_from_string (f.string_child ("ContentKind"));
- content_version = optional_type_child<ContentVersion> (f, "ContentVersion");
- f.ignore_child ("RatingList");
- reels = type_grand_children<Reel> (f, "ReelList", "Reel");
-
- f.ignore_child ("Issuer");
- f.ignore_child ("Signer");
- f.ignore_child ("Signature");
-
- f.done ();
-}
-
-ContentVersion::ContentVersion (shared_ptr<const cxml::Node> node)
-{
- id = node->optional_string_child ("Id").get_value_or ("");
- label_text = node->string_child ("LabelText");
- node->done ();
-}
-
-Reel::Reel (shared_ptr<const cxml::Node> node)
-{
- id = node->string_child ("Id");
- asset_list = type_child<CPLAssetList> (node, "AssetList");
-
- node->ignore_child ("AnnotationText");
- node->done ();
-}
-
-CPLAssetList::CPLAssetList (shared_ptr<const cxml::Node> node)
-{
- main_picture = optional_type_child<MainPicture> (node, "MainPicture");
- main_stereoscopic_picture = optional_type_child<MainStereoscopicPicture> (node, "MainStereoscopicPicture");
- main_sound = optional_type_child<MainSound> (node, "MainSound");
- main_subtitle = optional_type_child<MainSubtitle> (node, "MainSubtitle");
-
- node->done ();
-}
-
-MainPicture::MainPicture (shared_ptr<const cxml::Node> node)
- : Picture (node)
-{
-
-}
-
-MainStereoscopicPicture::MainStereoscopicPicture (shared_ptr<const cxml::Node> node)
- : Picture (node)
-{
-
-}
-
-Picture::Picture (shared_ptr<const cxml::Node> node)
-{
- id = node->string_child ("Id");
- annotation_text = node->optional_string_child ("AnnotationText").get_value_or ("");
- edit_rate = Fraction (node->string_child ("EditRate"));
- intrinsic_duration = node->number_child<int64_t> ("IntrinsicDuration");
- entry_point = node->number_child<int64_t> ("EntryPoint");
- duration = node->number_child<int64_t> ("Duration");
- frame_rate = Fraction (node->string_child ("FrameRate"));
- try {
- screen_aspect_ratio = Fraction (node->string_child ("ScreenAspectRatio"));
- } catch (XMLError& e) {
- /* Maybe it's not a fraction */
- }
- try {
- float f = node->number_child<float> ("ScreenAspectRatio");
- screen_aspect_ratio = Fraction (f * 1000, 1000);
- } catch (bad_cast& e) {
-
- }
-
- key_id = node->optional_string_child ("KeyId").get_value_or ("");
-
- node->ignore_child ("Hash");
-
- node->done ();
-}
-
-MainSound::MainSound (shared_ptr<const cxml::Node> node)
-{
- id = node->string_child ("Id");
- annotation_text = node->optional_string_child ("AnnotationText").get_value_or ("");
- edit_rate = Fraction (node->string_child ("EditRate"));
- intrinsic_duration = node->number_child<int64_t> ("IntrinsicDuration");
- entry_point = node->number_child<int64_t> ("EntryPoint");
- duration = node->number_child<int64_t> ("Duration");
- key_id = node->optional_string_child ("KeyId").get_value_or ("");
-
- node->ignore_child ("Hash");
- node->ignore_child ("Language");
-
- node->done ();
-}
-
-MainSubtitle::MainSubtitle (shared_ptr<const cxml::Node> node)
-{
- id = node->string_child ("Id");
- annotation_text = node->optional_string_child ("AnnotationText").get_value_or ("");
- edit_rate = Fraction (node->string_child ("EditRate"));
- intrinsic_duration = node->number_child<int64_t> ("IntrinsicDuration");
- entry_point = node->number_child<int64_t> ("EntryPoint");
- duration = node->number_child<int64_t> ("Duration");
-
- node->ignore_child ("Hash");
- node->ignore_child ("Language");
-
- node->done ();
-}
diff --git a/src/parse/cpl.h b/src/parse/cpl.h
deleted file mode 100644
index 4889a1c4..00000000
--- a/src/parse/cpl.h
+++ /dev/null
@@ -1,163 +0,0 @@
-/*
- Copyright (C) 2012 Carl Hetherington <cth@carlh.net>
-
- This program 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.
-
- This program 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 this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-*/
-
-/** @file src/parse/cpl.h
- * @brief Classes used to parse a CPL.
- */
-
-#include <stdint.h>
-#include <boost/shared_ptr.hpp>
-#include <libcxml/cxml.h>
-#include "../types.h"
-
-namespace dcp {
-
-namespace parse {
-
-/** @brief A simple representation of a CPL \<Picture\> node */
-class Picture
-{
-public:
- Picture () {}
- Picture (boost::shared_ptr<const cxml::Node> node);
-
- std::string id;
- std::string annotation_text;
- Fraction edit_rate;
- /** Duration of the whole thing */
- int64_t intrinsic_duration;
- /** Start point in frames */
- int64_t entry_point;
- /** Duration that will actually play */
- int64_t duration;
- Fraction frame_rate;
- Fraction screen_aspect_ratio;
- std::string key_id;
-};
-
-
-/** @brief A simple parser for and representation of a CPL \<MainPicture\> node */
-class MainPicture : public Picture
-{
-public:
- MainPicture () {}
- MainPicture (boost::shared_ptr<const cxml::Node> node);
-};
-
-/** @brief A simple parser for and representation of a CPL \<MainStereoscopicPicture\> node */
-class MainStereoscopicPicture : public Picture
-{
-public:
- MainStereoscopicPicture () {}
- MainStereoscopicPicture (boost::shared_ptr<const cxml::Node> node);
-};
-
-/** @brief A simple parser for and representation of a CPL \<MainSound\> node */
-class MainSound
-{
-public:
- MainSound () {}
- MainSound (boost::shared_ptr<const cxml::Node> node);
-
- std::string id;
- std::string annotation_text;
- Fraction edit_rate;
- int64_t intrinsic_duration;
- int64_t entry_point;
- int64_t duration;
- std::string key_id;
-};
-
-/** @brief A simple parser for and representation of a CPL \<MainSubtitle\> node */
-class MainSubtitle
-{
-public:
- MainSubtitle () {}
- MainSubtitle (boost::shared_ptr<const cxml::Node> node);
-
- std::string id;
- std::string annotation_text;
- Fraction edit_rate;
- int64_t intrinsic_duration;
- int64_t entry_point;
- int64_t duration;
-};
-
-/** @brief A simple parser for and representation of a CPL \<AssetList\> node */
-class CPLAssetList
-{
-public:
- CPLAssetList () {}
- CPLAssetList (boost::shared_ptr<const cxml::Node> node);
-
- boost::shared_ptr<MainPicture> main_picture;
- boost::shared_ptr<MainStereoscopicPicture> main_stereoscopic_picture;
- boost::shared_ptr<MainSound> main_sound;
- boost::shared_ptr<MainSubtitle> main_subtitle;
-};
-
-/** @brief A simple parser for and representation of a CPL \<Reel\> node */
-class Reel
-{
-public:
- Reel () {}
- Reel (boost::shared_ptr<const cxml::Node> node);
-
- std::string id;
- boost::shared_ptr<CPLAssetList> asset_list;
-};
-
-
-/** @brief A simple parser for and representation of a CPL \<ContentVersion\> node */
-class ContentVersion
-{
-public:
- ContentVersion () {}
- ContentVersion (boost::shared_ptr<const cxml::Node> node);
-
- std::string id;
- std::string label_text;
-};
-
-/** @class CPL
- * @brief Class to parse a CPL
- *
- * This class is used to parse XML CPL files. It is rarely necessary
- * for the caller to use it outside libdcp.
- */
-class CPL
-{
-public:
- /** Parse a CPL XML file into our member variables */
- CPL (std::string file);
-
- std::string id;
- std::string annotation_text;
- std::string issue_date;
- std::string creator;
- std::string content_title_text;
- ContentKind content_kind;
- boost::shared_ptr<ContentVersion> content_version;
- std::list<boost::shared_ptr<Reel> > reels;
-};
-
-}
-
-}
-
diff --git a/src/parse/pkl.cc b/src/parse/pkl.cc
deleted file mode 100644
index d0fa1556..00000000
--- a/src/parse/pkl.cc
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- Copyright (C) 2012 Carl Hetherington <cth@carlh.net>
-
- This program 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.
-
- This program 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 this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-*/
-
-/** @file src/pkl_file.cc
- * @brief Classes used to parse a PKL.
- */
-
-#include <iostream>
-#include "pkl.h"
-
-using namespace std;
-using namespace boost;
-using namespace dcp::parse;
-
-PKL::PKL (string file)
-{
- cxml::Document f ("PackingList");
- f.read_file (file);
-
- id = f.string_child ("Id");
- annotation_text = f.optional_string_child ("AnnotationText").get_value_or ("");
- issue_date = f.string_child ("IssueDate");
- issuer = f.string_child ("Issuer");
- creator = f.string_child ("Creator");
- assets = type_grand_children<PKLAsset> (f, "AssetList", "Asset");
-}
-
-PKLAsset::PKLAsset (boost::shared_ptr<const cxml::Node> node)
-{
- id = node->string_child ("Id");
- annotation_text = node->optional_string_child ("AnnotationText").get_value_or ("");
- hash = node->string_child ("Hash");
- size = node->number_child<int64_t> ("Size");
- type = node->string_child ("Type");
- original_file_name = node->optional_string_child ("OriginalFileName").get_value_or ("");
-}
diff --git a/src/picture_mxf.cc b/src/picture_mxf.cc
index 8f0f85b9..7634493d 100644
--- a/src/picture_mxf.cc
+++ b/src/picture_mxf.cc
@@ -17,10 +17,6 @@
*/
-/** @file src/picture_asset.cc
- * @brief An asset made up of JPEG2000 files
- */
-
#include <list>
#include <stdexcept>
#include <iostream>
@@ -58,33 +54,21 @@ PictureMXF::PictureMXF (boost::filesystem::path file)
}
-PictureMXF::PictureMXF (int edit_rate)
+PictureMXF::PictureMXF (Fraction edit_rate)
: MXF (edit_rate)
{
}
void
-PictureMXF::write_to_cpl (xmlpp::Element* node) const
+PictureMXF::read_picture_descriptor (ASDCP::JP2K::PictureDescriptor const & desc)
{
- MXF::write_to_cpl (node);
-
- xmlpp::Node::NodeList c = node->get_children ();
- xmlpp::Node::NodeList::iterator i = c.begin();
- while (i != c.end() && (*i)->get_name() != cpl_node_name ()) {
- ++i;
- }
-
- assert (i != c.end ());
-
- (*i)->add_child ("FrameRate")->add_child_text (lexical_cast<string> (_edit_rate * edit_rate_factor ()) + " 1");
- if (_interop) {
- stringstream s;
- s << std::fixed << std::setprecision (2) << (float (_size.width) / _size.height);
- (*i)->add_child ("ScreenAspectRatio")->add_child_text (s.str ());
- } else {
- (*i)->add_child ("ScreenAspectRatio")->add_child_text (lexical_cast<string> (_size.width) + " " + lexical_cast<string> (_size.height));
- }
+ _size.width = desc.StoredWidth;
+ _size.height = desc.StoredHeight;
+ _edit_rate = Fraction (desc.EditRate.Numerator, desc.EditRate.Denominator);
+ _intrinsic_duration = desc.ContainerDuration;
+ _frame_rate = Fraction (desc.SampleRate.Numerator, desc.SampleRate.Denominator);
+ _screen_aspect_ratio = Fraction (desc.AspectRatio.Numerator, desc.AspectRatio.Denominator);
}
bool
@@ -212,6 +196,3 @@ PictureMXF::key_type () const
{
return "MDIK";
}
-
-
-
diff --git a/src/picture_mxf.h b/src/picture_mxf.h
index 3a587280..df75625c 100644
--- a/src/picture_mxf.h
+++ b/src/picture_mxf.h
@@ -47,19 +47,27 @@ class PictureMXF : public MXF
{
public:
PictureMXF (boost::filesystem::path file);
- PictureMXF (int edit_rate);
+ PictureMXF (Fraction edit_rate);
- virtual boost::shared_ptr<PictureMXFWriter> start_write (boost::filesystem::path file, bool overwrite) = 0;
+ virtual boost::shared_ptr<PictureMXFWriter> start_write (boost::filesystem::path file, Standard standard, bool overwrite) = 0;
+
+ void write_to_pkl (xmlpp::Node* node) const;
Size size () const {
return _size;
}
- void set_size (Size s) {
- _size = s;
+ Fraction frame_rate () const {
+ return _frame_rate;
}
- void write_to_cpl (xmlpp::Element *) const;
+ Fraction screen_aspect_ratio () const {
+ return _screen_aspect_ratio;
+ }
+
+ Fraction edit_rate () const {
+ return _edit_rate;
+ }
protected:
@@ -72,8 +80,12 @@ protected:
ASDCP::JP2K::PictureDescriptor const & a, ASDCP::JP2K::PictureDescriptor const & b, boost::function<void (NoteType, std::string)>
) const;
+ void read_picture_descriptor (ASDCP::JP2K::PictureDescriptor const &);
+
/** picture size in pixels */
Size _size;
+ Fraction _frame_rate;
+ Fraction _screen_aspect_ratio;
private:
std::string key_type () const;
diff --git a/src/picture_mxf_writer.cc b/src/picture_mxf_writer.cc
index 1a128b33..46426401 100644
--- a/src/picture_mxf_writer.cc
+++ b/src/picture_mxf_writer.cc
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2012-2013 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -17,13 +17,13 @@
*/
-#include <inttypes.h>
-#include <stdint.h>
-#include "AS_DCP.h"
#include "KM_fileio.h"
#include "picture_mxf_writer.h"
#include "exceptions.h"
#include "picture_mxf.h"
+#include "AS_DCP.h"
+#include <inttypes.h>
+#include <stdint.h>
using std::istream;
using std::ostream;
@@ -82,14 +82,12 @@ FrameInfo::write (FILE* f) const
#endif
}
-
-PictureMXFWriter::PictureMXFWriter (PictureMXF* mxf, boost::filesystem::path file, bool overwrite)
- : _mxf (mxf)
- , _file (file)
- , _frames_written (0)
+PictureMXFWriter::PictureMXFWriter (PictureMXF* mxf, boost::filesystem::path file, Standard standard, bool overwrite)
+ : MXFWriter (mxf, file)
+ , _picture_mxf (mxf)
, _started (false)
- , _finalized (false)
+ , _standard (standard)
, _overwrite (overwrite)
{
-
+
}
diff --git a/src/picture_mxf_writer.h b/src/picture_mxf_writer.h
index bcd8873d..f8c67ba9 100644
--- a/src/picture_mxf_writer.h
+++ b/src/picture_mxf_writer.h
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2012-2013 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -17,13 +17,14 @@
*/
+#include "metadata.h"
+#include "types.h"
+#include "mxf_writer.h"
+#include <boost/shared_ptr.hpp>
+#include <boost/utility.hpp>
#include <stdint.h>
#include <string>
#include <fstream>
-#include <boost/shared_ptr.hpp>
-#include <boost/utility.hpp>
-#include "metadata.h"
-#include "types.h"
namespace dcp {
@@ -49,31 +50,21 @@ struct FrameInfo
std::string hash;
};
-class PictureMXFWriter : public boost::noncopyable
+class PictureMXFWriter : public MXFWriter
{
public:
- virtual ~PictureMXFWriter () {}
virtual FrameInfo write (uint8_t *, int) = 0;
- virtual void finalize () = 0;
virtual void fake_write (int) = 0;
protected:
template <class P, class Q>
- friend void start (PictureMXFWriter *, boost::shared_ptr<P>, Q *, uint8_t *, int);
-
- PictureMXFWriter (PictureMXF *, boost::filesystem::path, bool);
+ friend void start (PictureMXFWriter *, boost::shared_ptr<P>, Standard, Q *, uint8_t *, int);
- PictureMXF* _mxf;
+ PictureMXFWriter (PictureMXF *, boost::filesystem::path, Standard standard, bool);
- boost::filesystem::path _file;
- /** Number of picture frames written to the asset so far. For stereo assets
- * this will be incremented for each eye (i.e. there will be twice the number
- * of frames as in a mono asset).
- */
- int _frames_written;
+ PictureMXF* _picture_mxf;
bool _started;
- /** true if finalize() has been called */
- bool _finalized;
+ Standard _standard;
bool _overwrite;
};
diff --git a/src/picture_mxf_writer_common.cc b/src/picture_mxf_writer_common.cc
index 6ac8ae35..9836f03e 100644
--- a/src/picture_mxf_writer_common.cc
+++ b/src/picture_mxf_writer_common.cc
@@ -33,7 +33,7 @@ struct ASDCPStateBase
};
template <class P, class Q>
-void dcp::start (PictureMXFWriter* writer, shared_ptr<P> state, Q* mxf, uint8_t* data, int size)
+void dcp::start (PictureMXFWriter* writer, shared_ptr<P> state, Standard standard, Q* mxf, uint8_t* data, int size)
{
mxf->set_file (writer->_file);
@@ -42,9 +42,9 @@ void dcp::start (PictureMXFWriter* writer, shared_ptr<P> state, Q* mxf, uint8_t*
}
state->j2k_parser.FillPictureDescriptor (state->picture_descriptor);
- state->picture_descriptor.EditRate = ASDCP::Rational (mxf->edit_rate(), 1);
+ state->picture_descriptor.EditRate = ASDCP::Rational (mxf->edit_rate().numerator, mxf->edit_rate().denominator);
- mxf->fill_writer_info (&state->writer_info);
+ mxf->fill_writer_info (&state->writer_info, standard);
Kumu::Result_t r = state->mxf_writer.OpenWrite (
mxf->file().string().c_str(),
diff --git a/src/reel.cc b/src/reel.cc
index 9f514d88..27fc0329 100644
--- a/src/reel.cc
+++ b/src/reel.cc
@@ -17,15 +17,19 @@
*/
-#include <libxml++/nodes/element.h>
#include "reel.h"
#include "util.h"
#include "picture_mxf.h"
#include "mono_picture_mxf.h"
#include "stereo_picture_mxf.h"
#include "sound_mxf.h"
-#include "subtitle_asset.h"
+#include "subtitle_content.h"
+#include "reel_mono_picture_asset.h"
+#include "reel_stereo_picture_asset.h"
+#include "reel_sound_asset.h"
+#include "reel_subtitle_asset.h"
#include "kdm.h"
+#include <libxml++/nodes/element.h>
using std::string;
using std::list;
@@ -34,8 +38,37 @@ using boost::shared_ptr;
using boost::dynamic_pointer_cast;
using namespace dcp;
+Reel::Reel (shared_ptr<const cxml::Node> node)
+ : Object (node->string_child ("Id"))
+{
+ shared_ptr<cxml::Node> asset_list = node->node_child ("AssetList");
+
+ shared_ptr<cxml::Node> main_picture = asset_list->optional_node_child ("MainPicture");
+ if (main_picture) {
+ _main_picture.reset (new ReelMonoPictureAsset (main_picture));
+ }
+
+ shared_ptr<cxml::Node> main_stereoscopic_picture = asset_list->optional_node_child ("MainStereoscopicPicture");
+ if (main_stereoscopic_picture) {
+ _main_picture.reset (new ReelStereoPictureAsset (main_stereoscopic_picture));
+ }
+
+ shared_ptr<cxml::Node> main_sound = asset_list->optional_node_child ("MainSound");
+ if (main_sound) {
+ _main_sound.reset (new ReelSoundAsset (main_sound));
+ }
+
+ shared_ptr<cxml::Node> main_subtitle = asset_list->optional_node_child ("MainSubtitle");
+ if (main_subtitle) {
+ _main_subtitle.reset (new ReelSubtitleAsset (main_subtitle));
+ }
+
+ node->ignore_child ("AnnotationText");
+ node->done ();
+}
+
void
-Reel::write_to_cpl (xmlpp::Element* node) const
+Reel::write_to_cpl (xmlpp::Element* node, Standard standard) const
{
xmlpp::Element* reel = node->add_child ("Reel");
reel->add_child("Id")->add_child_text ("urn:uuid:" + make_uuid());
@@ -43,20 +76,20 @@ Reel::write_to_cpl (xmlpp::Element* node) const
if (_main_picture && dynamic_pointer_cast<MonoPictureMXF> (_main_picture)) {
/* Mono pictures come before other stuff... */
- _main_picture->write_to_cpl (asset_list);
+ _main_picture->write_to_cpl (asset_list, standard);
}
if (_main_sound) {
- _main_sound->write_to_cpl (asset_list);
+ _main_sound->write_to_cpl (asset_list, standard);
}
if (_main_subtitle) {
- _main_subtitle->write_to_cpl (asset_list);
+ _main_subtitle->write_to_cpl (asset_list, standard);
}
if (_main_picture && dynamic_pointer_cast<StereoPictureMXF> (_main_picture)) {
/* ... but stereo pictures must come after */
- _main_picture->write_to_cpl (asset_list);
+ _main_picture->write_to_cpl (asset_list, standard);
}
}
@@ -106,10 +139,10 @@ Reel::add_kdm (KDM const & kdm)
for (list<KDMKey>::iterator i = keys.begin(); i != keys.end(); ++i) {
if (i->key_id() == _main_picture->key_id()) {
- _main_picture->set_key (i->key ());
+ _main_picture->mxf()->set_key (i->key ());
}
if (i->key_id() == _main_sound->key_id()) {
- _main_sound->set_key (i->key ());
+ _main_sound->mxf()->set_key (i->key ());
}
}
}
@@ -117,10 +150,25 @@ Reel::add_kdm (KDM const & kdm)
void
Reel::set_mxf_keys (Key key)
{
- _main_picture->set_key (key);
+ _main_picture->mxf()->set_key (key);
if (_main_sound) {
- _main_sound->set_key (key);
+ _main_sound->mxf()->set_key (key);
}
/* XXX: subtitle asset? */
}
+
+void
+Reel::add (shared_ptr<ReelAsset> asset)
+{
+ shared_ptr<ReelPictureAsset> p = dynamic_pointer_cast<ReelPictureAsset> (asset);
+ shared_ptr<ReelSoundAsset> so = dynamic_pointer_cast<ReelSoundAsset> (asset);
+ shared_ptr<ReelSubtitleAsset> su = dynamic_pointer_cast<ReelSubtitleAsset> (asset);
+ if (p) {
+ _main_picture = p;
+ } else if (so) {
+ _main_sound = so;
+ } else if (su) {
+ _main_subtitle = su;
+ }
+}
diff --git a/src/reel.h b/src/reel.h
index 41e811e4..8aaebf51 100644
--- a/src/reel.h
+++ b/src/reel.h
@@ -20,51 +20,59 @@
#ifndef LIBDCP_REEL_H
#define LIBDCP_REEL_H
-#include <list>
-#include <boost/shared_ptr.hpp>
-#include <boost/function.hpp>
-#include <libxml++/libxml++.h>
#include "key.h"
#include "types.h"
+#include "ref.h"
+#include <libxml++/libxml++.h>
+#include <boost/shared_ptr.hpp>
+#include <boost/function.hpp>
+#include <list>
-namespace xmlpp {
+namespace cxml {
class Node;
}
namespace dcp {
-class PictureMXF;
-class SoundMXF;
-class SubtitleAsset;
-class KDM;
+class KDM;
+class ReelAsset;
+class ReelPictureAsset;
+class ReelSoundAsset;
+class ReelSubtitleAsset;
/** @brief A reel within a DCP; the part which actually contains picture, sound and subtitle data */
-class Reel
+class Reel : public Object
{
public:
+ Reel () {}
+
Reel (
- boost::shared_ptr<PictureMXF> picture,
- boost::shared_ptr<SoundMXF> sound,
- boost::shared_ptr<SubtitleAsset> subtitle
+ boost::shared_ptr<ReelPictureAsset> picture,
+ boost::shared_ptr<ReelSoundAsset> sound,
+ boost::shared_ptr<ReelSubtitleAsset> subtitle
)
: _main_picture (picture)
, _main_sound (sound)
, _main_subtitle (subtitle)
{}
+
+ Reel (boost::shared_ptr<const cxml::Node>);
- boost::shared_ptr<const PictureMXF> main_picture () const {
+ boost::shared_ptr<ReelPictureAsset> main_picture () const {
return _main_picture;
}
- boost::shared_ptr<const SoundMXF> main_sound () const {
+ boost::shared_ptr<ReelSoundAsset> main_sound () const {
return _main_sound;
}
- boost::shared_ptr<const SubtitleAsset> main_subtitle () const {
+ boost::shared_ptr<ReelSubtitleAsset> main_subtitle () const {
return _main_subtitle;
}
- void write_to_cpl (xmlpp::Element *) const;
+ void add (boost::shared_ptr<ReelAsset> asset);
+
+ void write_to_cpl (xmlpp::Element* node, Standard standard) const;
bool encrypted () const;
@@ -75,9 +83,9 @@ public:
void add_kdm (KDM const &);
private:
- boost::shared_ptr<PictureMXF> _main_picture;
- boost::shared_ptr<SoundMXF> _main_sound;
- boost::shared_ptr<SubtitleAsset> _main_subtitle;
+ boost::shared_ptr<ReelPictureAsset> _main_picture;
+ boost::shared_ptr<ReelSoundAsset> _main_sound;
+ boost::shared_ptr<ReelSubtitleAsset> _main_subtitle;
};
}
diff --git a/src/reel_asset.cc b/src/reel_asset.cc
new file mode 100644
index 00000000..8e03b5c4
--- /dev/null
+++ b/src/reel_asset.cc
@@ -0,0 +1,101 @@
+/*
+ Copyright (C) 2014 Carl Hetherington <cth@carlh.net>
+
+ This program 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.
+
+ This program 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 this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#include "reel_asset.h"
+#include "content.h"
+#include "compose.hpp"
+#include <libcxml/cxml.h>
+
+using std::pair;
+using std::string;
+using std::make_pair;
+using boost::shared_ptr;
+using boost::lexical_cast;
+using namespace dcp;
+
+ReelAsset::ReelAsset ()
+ : Object (make_uuid ())
+ , _content (_id)
+ , _edit_rate (Fraction (24, 1))
+ , _intrinsic_duration (0)
+ , _entry_point (0)
+ , _duration (0)
+{
+
+}
+
+ReelAsset::ReelAsset (shared_ptr<Content> content, int64_t entry_point)
+ : Object (content->id ())
+ , _content (content)
+ , _edit_rate (content->edit_rate ())
+ , _intrinsic_duration (content->intrinsic_duration ())
+ , _entry_point (entry_point)
+ , _duration (_intrinsic_duration - _entry_point)
+ , _hash (make_digest (content->file (), 0))
+{
+
+}
+
+ReelAsset::ReelAsset (shared_ptr<const cxml::Node> node)
+ : Object (node->string_child ("Id"))
+ , _content (_id)
+ , _annotation_text (node->optional_string_child ("AnnotationText").get_value_or (""))
+ , _edit_rate (Fraction (node->string_child ("EditRate")))
+ , _intrinsic_duration (node->number_child<int64_t> ("IntrinsicDuration"))
+ , _entry_point (node->number_child<int64_t> ("EntryPoint"))
+ , _duration (node->number_child<int64_t> ("Duration"))
+ , _hash (node->string_child ("Hash"))
+ , _key_id (node->optional_string_child ("KeyId").get_value_or (""))
+{
+ if (_id.length() > 9) {
+ _id = _id.substr (9);
+ _content.set_id (_id);
+ }
+
+ if (_key_id.length() > 9) {
+ _key_id = _key_id.substr (9);
+ }
+
+ node->done ();
+}
+
+void
+ReelAsset::write_to_cpl (xmlpp::Node* node, Standard) const
+{
+ pair<string, string> const attr = cpl_node_attribute ();
+ xmlpp::Element* a = node->add_child (cpl_node_name ());
+ if (!attr.first.empty ()) {
+ a->set_attribute (attr.first, attr.second);
+ }
+ a->add_child("Id")->add_child_text ("urn:uuid:" + _id);
+ a->add_child("AnnotationText")->add_child_text (_annotation_text);
+ a->add_child("EditRate")->add_child_text (String::compose ("%1 %2", _edit_rate.numerator, _edit_rate.denominator));
+ a->add_child("IntrinsicDuration")->add_child_text (lexical_cast<string> (_intrinsic_duration));
+ a->add_child("EntryPoint")->add_child_text (lexical_cast<string> (_entry_point));
+ a->add_child("Duration")->add_child_text (lexical_cast<string> (_duration));
+ if (!_key_id.empty ()) {
+ a->add_child("KeyId")->add_child_text ("urn:uuid:" + _key_id);
+ }
+}
+
+pair<string, string>
+ReelAsset::cpl_node_attribute () const
+{
+ return make_pair ("", "");
+}
diff --git a/src/reel_asset.h b/src/reel_asset.h
new file mode 100644
index 00000000..5207166a
--- /dev/null
+++ b/src/reel_asset.h
@@ -0,0 +1,82 @@
+/*
+ Copyright (C) 2014 Carl Hetherington <cth@carlh.net>
+
+ This program 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.
+
+ This program 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 this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#ifndef LIBDCP_REEL_ASSET_H
+#define LIBDCP_REEL_ASSET_H
+
+#include "object.h"
+#include "util.h"
+#include "ref.h"
+#include <boost/shared_ptr.hpp>
+
+namespace cxml {
+ class Node;
+}
+
+namespace xmlpp {
+ class Node;
+}
+
+namespace dcp {
+
+class Content;
+
+class ReelAsset : public Object
+{
+public:
+ ReelAsset ();
+ ReelAsset (boost::shared_ptr<Content> content, int64_t entry_point);
+ ReelAsset (boost::shared_ptr<const cxml::Node>);
+
+ Ref<Content> content () const {
+ return _content;
+ }
+
+ bool encrypted () const {
+ return !_key_id.empty ();
+ }
+
+ std::string key_id () const {
+ return _key_id;
+ }
+
+ virtual void write_to_cpl (xmlpp::Node* node, Standard standard) const;
+ virtual bool equals (boost::shared_ptr<const ReelAsset>, EqualityOptions, boost::function<void (NoteType, std::string)>) const {
+ return false;
+ }
+
+protected:
+ virtual std::string cpl_node_name () const = 0;
+ virtual std::pair<std::string, std::string> cpl_node_attribute () const;
+
+ Ref<Content> _content;
+
+private:
+ std::string _annotation_text;
+ Fraction _edit_rate;
+ int64_t _intrinsic_duration;
+ int64_t _entry_point;
+ int64_t _duration;
+ std::string _hash;
+ std::string _key_id;
+};
+
+}
+
+#endif
diff --git a/src/reel_mono_picture_asset.cc b/src/reel_mono_picture_asset.cc
new file mode 100644
index 00000000..892c9f4e
--- /dev/null
+++ b/src/reel_mono_picture_asset.cc
@@ -0,0 +1,49 @@
+/*
+ Copyright (C) 2014 Carl Hetherington <cth@carlh.net>
+
+ This program 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.
+
+ This program 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 this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#include "reel_mono_picture_asset.h"
+#include "mono_picture_mxf.h"
+
+using std::string;
+using boost::shared_ptr;
+using namespace dcp;
+
+ReelMonoPictureAsset::ReelMonoPictureAsset ()
+{
+
+}
+
+ReelMonoPictureAsset::ReelMonoPictureAsset (shared_ptr<MonoPictureMXF> mxf, int64_t entry_point)
+ : ReelPictureAsset (mxf, entry_point)
+{
+
+}
+
+ReelMonoPictureAsset::ReelMonoPictureAsset (shared_ptr<const cxml::Node> node)
+ : ReelPictureAsset (node)
+{
+
+}
+
+string
+ReelMonoPictureAsset::cpl_node_name () const
+{
+ return "MainPicture";
+}
+
diff --git a/src/reel_mono_picture_asset.h b/src/reel_mono_picture_asset.h
new file mode 100644
index 00000000..881bbec0
--- /dev/null
+++ b/src/reel_mono_picture_asset.h
@@ -0,0 +1,40 @@
+/*
+ Copyright (C) 2014 Carl Hetherington <cth@carlh.net>
+
+ This program 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.
+
+ This program 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 this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#include "reel_picture_asset.h"
+
+namespace dcp {
+
+class MonoPictureMXF;
+
+class ReelMonoPictureAsset : public ReelPictureAsset
+{
+public:
+ ReelMonoPictureAsset ();
+ ReelMonoPictureAsset (boost::shared_ptr<MonoPictureMXF> content, int64_t entry_point);
+ ReelMonoPictureAsset (boost::shared_ptr<const cxml::Node>);
+
+private:
+ std::string cpl_node_name () const;
+};
+
+}
+
+
+
diff --git a/src/reel_picture_asset.cc b/src/reel_picture_asset.cc
new file mode 100644
index 00000000..9fdc3b9e
--- /dev/null
+++ b/src/reel_picture_asset.cc
@@ -0,0 +1,88 @@
+/*
+ Copyright (C) 2014 Carl Hetherington <cth@carlh.net>
+
+ This program 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.
+
+ This program 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 this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#include "content.h"
+#include "reel_picture_asset.h"
+#include "picture_mxf.h"
+#include "compose.hpp"
+#include <libcxml/cxml.h>
+
+using std::bad_cast;
+using std::string;
+using std::stringstream;
+using boost::shared_ptr;
+using boost::lexical_cast;
+using namespace dcp;
+
+ReelPictureAsset::ReelPictureAsset ()
+ : _frame_rate (Fraction (24, 1))
+ , _screen_aspect_ratio (Fraction (1998, 1080))
+{
+
+}
+
+ReelPictureAsset::ReelPictureAsset (shared_ptr<PictureMXF> content, int64_t entry_point)
+ : ReelAsset (content, entry_point)
+ , _frame_rate (content->frame_rate ())
+ , _screen_aspect_ratio (content->screen_aspect_ratio ())
+{
+
+}
+
+ReelPictureAsset::ReelPictureAsset (shared_ptr<const cxml::Node> node)
+ : ReelAsset (node)
+{
+ _frame_rate = Fraction (node->string_child ("FrameRate"));
+ try {
+ _screen_aspect_ratio = Fraction (node->string_child ("ScreenAspectRatio"));
+ } catch (XMLError& e) {
+ /* Maybe it's not a fraction */
+ }
+ try {
+ float f = node->number_child<float> ("ScreenAspectRatio");
+ _screen_aspect_ratio = Fraction (f * 1000, 1000);
+ } catch (bad_cast& e) {
+
+ }
+}
+
+void
+ReelPictureAsset::write_to_cpl (xmlpp::Node* node, Standard standard) const
+{
+ ReelAsset::write_to_cpl (node, standard);
+
+ xmlpp::Node::NodeList c = node->get_children ();
+ xmlpp::Node::NodeList::iterator i = c.begin();
+ while (i != c.end() && (*i)->get_name() != cpl_node_name ()) {
+ ++i;
+ }
+
+ assert (i != c.end ());
+
+ (*i)->add_child ("FrameRate")->add_child_text (String::compose ("%1 %2", _frame_rate.numerator, _frame_rate.denominator));
+ if (standard == INTEROP) {
+ stringstream s;
+ s << std::fixed << std::setprecision (2) << (float (_screen_aspect_ratio.numerator) / _screen_aspect_ratio.denominator);
+ (*i)->add_child ("ScreenAspectRatio")->add_child_text (s.str ());
+ } else {
+ (*i)->add_child ("ScreenAspectRatio")->add_child_text (
+ String::compose ("%1 %2", _screen_aspect_ratio.numerator, _screen_aspect_ratio.denominator)
+ );
+ }
+}
diff --git a/src/reel_picture_asset.h b/src/reel_picture_asset.h
new file mode 100644
index 00000000..c6eb2c73
--- /dev/null
+++ b/src/reel_picture_asset.h
@@ -0,0 +1,52 @@
+/*
+ Copyright (C) 2014 Carl Hetherington <cth@carlh.net>
+
+ This program 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.
+
+ This program 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 this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#ifndef LIBDCP_REEL_PICTURE_ASSET_H
+#define LIBDCP_REEL_PICTURE_ASSET_H
+
+#include "reel_asset.h"
+#include "picture_mxf.h"
+
+namespace dcp {
+
+class ReelPictureAsset : public ReelAsset
+{
+public:
+ ReelPictureAsset ();
+ ReelPictureAsset (boost::shared_ptr<PictureMXF> content, int64_t entry_point);
+ ReelPictureAsset (boost::shared_ptr<const cxml::Node>);
+
+ boost::shared_ptr<PictureMXF> mxf () {
+ return boost::dynamic_pointer_cast<PictureMXF> (_content.object ());
+ }
+
+ void set_screen_aspect_ratio (Fraction a) {
+ _screen_aspect_ratio = a;
+ }
+
+ virtual void write_to_cpl (xmlpp::Node* node, Standard standard) const;
+
+private:
+ Fraction _frame_rate;
+ Fraction _screen_aspect_ratio;
+};
+
+}
+
+#endif
diff --git a/src/reel_sound_asset.cc b/src/reel_sound_asset.cc
new file mode 100644
index 00000000..6ef473fe
--- /dev/null
+++ b/src/reel_sound_asset.cc
@@ -0,0 +1,44 @@
+/*
+ Copyright (C) 2014 Carl Hetherington <cth@carlh.net>
+
+ This program 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.
+
+ This program 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 this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#include "reel_sound_asset.h"
+#include <libcxml/cxml.h>
+
+using std::string;
+using boost::shared_ptr;
+using namespace dcp;
+
+ReelSoundAsset::ReelSoundAsset (shared_ptr<Content> content, int64_t entry_point)
+ : ReelAsset (content, entry_point)
+{
+
+}
+
+ReelSoundAsset::ReelSoundAsset (shared_ptr<const cxml::Node> node)
+ : ReelAsset (node)
+{
+ node->ignore_child ("Language");
+ node->done ();
+}
+
+string
+ReelSoundAsset::cpl_node_name () const
+{
+ return "MainSound";
+}
diff --git a/src/reel_sound_asset.h b/src/reel_sound_asset.h
new file mode 100644
index 00000000..27d2499f
--- /dev/null
+++ b/src/reel_sound_asset.h
@@ -0,0 +1,42 @@
+/*
+ Copyright (C) 2014 Carl Hetherington <cth@carlh.net>
+
+ This program 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.
+
+ This program 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 this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#include "reel_asset.h"
+#include "sound_mxf.h"
+#include <boost/shared_ptr.hpp>
+#include <string>
+
+namespace dcp {
+
+class ReelSoundAsset : public ReelAsset
+{
+public:
+ ReelSoundAsset (boost::shared_ptr<Content> content, int64_t entry_point);
+ ReelSoundAsset (boost::shared_ptr<const cxml::Node>);
+
+ boost::shared_ptr<SoundMXF> mxf () {
+ return boost::dynamic_pointer_cast<SoundMXF> (_content.object ());
+ }
+
+private:
+ std::string cpl_node_name () const;
+};
+
+}
+
diff --git a/src/reel_stereo_picture_asset.cc b/src/reel_stereo_picture_asset.cc
new file mode 100644
index 00000000..2715eb34
--- /dev/null
+++ b/src/reel_stereo_picture_asset.cc
@@ -0,0 +1,50 @@
+/*
+ Copyright (C) 2014 Carl Hetherington <cth@carlh.net>
+
+ This program 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.
+
+ This program 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 this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#include "reel_stereo_picture_asset.h"
+
+using std::string;
+using std::pair;
+using std::make_pair;
+using boost::shared_ptr;
+using namespace dcp;
+
+ReelStereoPictureAsset::ReelStereoPictureAsset (shared_ptr<const cxml::Node> node)
+ : ReelPictureAsset (node)
+{
+
+}
+
+string
+ReelStereoPictureAsset::cpl_node_name () const
+{
+ return "msp-cpl:MainStereoscopicPicture";
+}
+
+pair<string, string>
+ReelStereoPictureAsset::cpl_node_attribute (Standard standard) const
+{
+ if (standard == INTEROP) {
+ return make_pair ("xmlns:msp-cpl", "http://www.digicine.com/schemas/437-Y/2007/Main-Stereo-Picture-CPL");
+ } else {
+ return make_pair ("xmlns:msp-cpl", "http://www.smpte-ra.org/schemas/429-10/2008/Main-Stereo-Picture-CPL");
+ }
+
+ return make_pair ("", "");
+}
diff --git a/src/reel_stereo_picture_asset.h b/src/reel_stereo_picture_asset.h
new file mode 100644
index 00000000..6ae67217
--- /dev/null
+++ b/src/reel_stereo_picture_asset.h
@@ -0,0 +1,37 @@
+/*
+ Copyright (C) 2014 Carl Hetherington <cth@carlh.net>
+
+ This program 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.
+
+ This program 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 this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#include "reel_picture_asset.h"
+
+namespace dcp {
+
+class ReelStereoPictureAsset : public ReelPictureAsset
+{
+public:
+ ReelStereoPictureAsset (boost::shared_ptr<const cxml::Node>);
+
+private:
+ std::string cpl_node_name () const;
+ std::pair<std::string, std::string> cpl_node_attribute (Standard standard) const;
+};
+
+}
+
+
+
diff --git a/src/reel_subtitle_asset.cc b/src/reel_subtitle_asset.cc
new file mode 100644
index 00000000..326e343c
--- /dev/null
+++ b/src/reel_subtitle_asset.cc
@@ -0,0 +1,44 @@
+/*
+ Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
+
+ This program 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.
+
+ This program 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 this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#include "subtitle_content.h"
+#include "reel_subtitle_asset.h"
+
+using std::string;
+using boost::shared_ptr;
+using namespace dcp;
+
+ReelSubtitleAsset::ReelSubtitleAsset (shared_ptr<SubtitleContent> content, int64_t entry_point)
+ : ReelAsset (content, entry_point)
+{
+
+}
+
+ReelSubtitleAsset::ReelSubtitleAsset (shared_ptr<const cxml::Node> node)
+ : ReelAsset (node)
+{
+ node->ignore_child ("Language");
+ node->done ();
+}
+
+string
+ReelSubtitleAsset::cpl_node_name () const
+{
+ return "MainSubtitle";
+}
diff --git a/src/parse/pkl.h b/src/reel_subtitle_asset.h
index f31eef7d..7b17b8a9 100644
--- a/src/parse/pkl.h
+++ b/src/reel_subtitle_asset.h
@@ -17,44 +17,24 @@
*/
-/** @file src/parse/pkl.h
- * @brief Classes used to parse a PKL
- */
-
-#include <boost/shared_ptr.hpp>
-#include "../xml.h"
+#include "reel_asset.h"
namespace dcp {
-namespace parse {
+class SubtitleContent;
-class PKLAsset
+class ReelSubtitleAsset : public ReelAsset
{
public:
- PKLAsset () {}
- PKLAsset (boost::shared_ptr<const cxml::Node>);
-
- std::string id;
- std::string annotation_text;
- std::string hash;
- int64_t size;
- std::string type;
- std::string original_file_name;
-};
+ ReelSubtitleAsset (boost::shared_ptr<SubtitleContent> content, int64_t entry_point);
+ ReelSubtitleAsset (boost::shared_ptr<const cxml::Node>);
-class PKL
-{
-public:
- PKL (std::string file);
-
- std::string id;
- std::string annotation_text;
- std::string issue_date;
- std::string issuer;
- std::string creator;
- std::list<boost::shared_ptr<PKLAsset> > assets;
+ boost::shared_ptr<SubtitleContent> subtitle_content () const {
+ return boost::dynamic_pointer_cast<SubtitleContent> (_content.object ());
+ }
+
+private:
+ std::string cpl_node_name () const;
};
-
-}
}
diff --git a/src/ref.h b/src/ref.h
new file mode 100644
index 00000000..db39bfb6
--- /dev/null
+++ b/src/ref.h
@@ -0,0 +1,91 @@
+/*
+ Copyright (C) 2014 Carl Hetherington <cth@carlh.net>
+
+ This program 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.
+
+ This program 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 this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#ifndef LIBDCP_REF_H
+#define LIBDCP_REF_H
+
+#include "exceptions.h"
+#include "object.h"
+#include <boost/shared_ptr.hpp>
+#include <string>
+
+namespace dcp {
+
+template<class T>
+class Ref
+{
+public:
+ Ref (std::string id)
+ : _id (id)
+ {}
+
+ Ref (boost::shared_ptr<T> object)
+ : _id (object->id ())
+ , _object (object)
+ {}
+
+ void set_id (std::string id)
+ {
+ _id = id;
+ }
+
+ void resolve (std::list<boost::shared_ptr<Object> > objects)
+ {
+ typename std::list<boost::shared_ptr<Object> >::iterator i = objects.begin();
+ while (i != objects.end() && (*i)->id() != _id) {
+ ++i;
+ }
+
+ if (i != objects.end ()) {
+ _object = boost::dynamic_pointer_cast<T> (*i);
+ }
+ }
+
+ std::string id () const {
+ return _id;
+ }
+
+ boost::shared_ptr<T> object () const {
+ if (!_object) {
+ throw UnresolvedRefError (_id);
+ }
+
+ return _object;
+ }
+
+ T * operator->() const {
+ if (!_object) {
+ throw UnresolvedRefError (_id);
+ }
+
+ return _object.get ();
+ }
+
+ bool resolved () const {
+ return _object;
+ }
+
+private:
+ std::string _id;
+ boost::shared_ptr<T> _object;
+};
+
+}
+
+#endif
diff --git a/src/signer.cc b/src/signer.cc
index ea13563f..4c5d199a 100644
--- a/src/signer.cc
+++ b/src/signer.cc
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2013 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2013-2014 Carl Hetherington <cth@carlh.net>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -17,14 +17,18 @@
*/
+/** @file src/signer.cc
+ * @brief Signer class.
+ */
+
+#include "signer.h"
+#include "exceptions.h"
+#include <libcxml/cxml.h>
#include <libxml++/libxml++.h>
#include <xmlsec/xmldsig.h>
#include <xmlsec/dl.h>
#include <xmlsec/app.h>
#include <xmlsec/crypto.h>
-#include <libcxml/cxml.h>
-#include "signer.h"
-#include "exceptions.h"
using std::string;
using std::list;
@@ -32,18 +36,30 @@ using std::cout;
using boost::shared_ptr;
using namespace dcp;
-/** @param signer_key Filename of private key to sign with */
+/** Add a &lt;Signer&gt; and &lt;ds:Signature&gt; nodes to an XML node.
+ * @param parent XML node to add to.
+ * @param interop true to use Interop standards, false for SMPTE.
+ */
void
-Signer::sign (xmlpp::Element* parent, bool interop) const
+Signer::sign (xmlpp::Element* parent, Standard standard) const
{
- add_signer (parent, "dsig");
+ /* <Signer> */
+
+ xmlpp::Element* signer = parent->add_child("Signer");
+ xmlpp::Element* data = signer->add_child("X509Data", "dsig");
+ xmlpp::Element* serial_element = data->add_child("X509IssuerSerial", "dsig");
+ serial_element->add_child("X509IssuerName", "dsig")->add_child_text (_certificates.leaf()->issuer());
+ serial_element->add_child("X509SerialNumber", "dsig")->add_child_text (_certificates.leaf()->serial());
+ data->add_child("X509SubjectName", "dsig")->add_child_text (_certificates.leaf()->subject());
+ /* <Signature> */
+
xmlpp::Element* signature = parent->add_child("Signature", "dsig");
xmlpp::Element* signed_info = signature->add_child ("SignedInfo", "dsig");
signed_info->add_child("CanonicalizationMethod", "dsig")->set_attribute ("Algorithm", "http://www.w3.org/TR/2001/REC-xml-c14n-20010315");
- if (interop) {
+ if (standard == INTEROP) {
signed_info->add_child("SignatureMethod", "dsig")->set_attribute("Algorithm", "http://www.w3.org/2000/09/xmldsig#rsa-sha1");
} else {
signed_info->add_child("SignatureMethod", "dsig")->set_attribute("Algorithm", "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256");
@@ -113,21 +129,3 @@ Signer::add_signature_value (xmlpp::Node* parent, string ns) const
xmlSecDSigCtxDestroy (signature_context);
}
-
-void
-Signer::add_signer (xmlpp::Element* parent, string ns) const
-{
- xmlpp::Element* signer = parent->add_child("Signer");
-
- {
- xmlpp::Element* data = signer->add_child("X509Data", ns);
-
- {
- xmlpp::Element* serial_element = data->add_child("X509IssuerSerial", ns);
- serial_element->add_child("X509IssuerName", ns)->add_child_text (_certificates.leaf()->issuer());
- serial_element->add_child("X509SerialNumber", ns)->add_child_text (_certificates.leaf()->serial());
- }
-
- data->add_child("X509SubjectName", ns)->add_child_text (_certificates.leaf()->subject());
- }
-}
diff --git a/src/signer.h b/src/signer.h
index 7c2864fd..c57c73cf 100644
--- a/src/signer.h
+++ b/src/signer.h
@@ -17,8 +17,13 @@
*/
-#include <boost/filesystem.hpp>
+/** @file src/signer.h
+ * @brief Signer class.
+ */
+
#include "certificates.h"
+#include "types.h"
+#include <boost/filesystem.hpp>
namespace xmlpp {
class Element;
@@ -27,15 +32,21 @@ namespace xmlpp {
namespace dcp {
+/** @class Signer
+ * @brief A class which can sign XML files.
+ */
class Signer
{
public:
+ /** @param c Certificate chain to sign with.
+ * @param k Key to sign with.
+ */
Signer (CertificateChain c, boost::filesystem::path k)
: _certificates (c)
, _key (k)
{}
- void sign (xmlpp::Element* parent, bool interop) const;
+ void sign (xmlpp::Element* parent, Standard standard) const;
void add_signature_value (xmlpp::Node* parent, std::string ns) const;
CertificateChain const & certificates () const {
@@ -44,8 +55,7 @@ public:
private:
- void add_signer (xmlpp::Element* parent, std::string ns) const;
-
+ /** Certificate chain to sign with */
CertificateChain _certificates;
/** Filename of signer key */
boost::filesystem::path _key;
diff --git a/src/sound_mxf.cc b/src/sound_mxf.cc
index 63f9ba05..82ab0823 100644
--- a/src/sound_mxf.cc
+++ b/src/sound_mxf.cc
@@ -32,6 +32,7 @@
#include "util.h"
#include "exceptions.h"
#include "sound_frame.h"
+#include "sound_mxf_writer.h"
using std::string;
using std::stringstream;
@@ -60,15 +61,17 @@ SoundMXF::SoundMXF (boost::filesystem::path file)
_sampling_rate = desc.AudioSamplingRate.Numerator / desc.AudioSamplingRate.Denominator;
_channels = desc.ChannelCount;
- _edit_rate = desc.EditRate.Numerator;
- assert (desc.EditRate.Denominator == 1);
+ _edit_rate = Fraction (desc.EditRate.Numerator, desc.EditRate.Denominator);
+
_intrinsic_duration = desc.ContainerDuration;
}
-string
-SoundMXF::cpl_node_name () const
+SoundMXF::SoundMXF (Fraction edit_rate, int sampling_rate, int channels)
+ : MXF (edit_rate)
+ , _channels (channels)
+ , _sampling_rate (sampling_rate)
{
- return "MainSound";
+
}
bool
@@ -155,105 +158,10 @@ SoundMXF::get_frame (int n) const
}
shared_ptr<SoundMXFWriter>
-SoundMXF::start_write ()
+SoundMXF::start_write (boost::filesystem::path file, Standard standard)
{
/* XXX: can't we use a shared_ptr here? */
- return shared_ptr<SoundMXFWriter> (new SoundMXFWriter (this));
-}
-
-struct SoundMXFWriter::ASDCPState
-{
- ASDCP::PCM::MXFWriter mxf_writer;
- ASDCP::PCM::FrameBuffer frame_buffer;
- ASDCP::WriterInfo writer_info;
- ASDCP::PCM::AudioDescriptor audio_desc;
- ASDCP::AESEncContext* encryption_context;
-};
-
-SoundMXFWriter::SoundMXFWriter (SoundMXF* a)
- : _state (new SoundMXFWriter::ASDCPState)
- , _asset (a)
- , _finalized (false)
- , _frames_written (0)
- , _frame_buffer_offset (0)
-{
- _state->encryption_context = a->encryption_context ();
-
- /* Derived from ASDCP::Wav::SimpleWaveHeader::FillADesc */
- _state->audio_desc.EditRate = ASDCP::Rational (_asset->edit_rate(), 1);
- _state->audio_desc.AudioSamplingRate = ASDCP::Rational (_asset->sampling_rate(), 1);
- _state->audio_desc.Locked = 0;
- _state->audio_desc.ChannelCount = _asset->channels ();
- _state->audio_desc.QuantizationBits = 24;
- _state->audio_desc.BlockAlign = 3 * _asset->channels();
- _state->audio_desc.AvgBps = _asset->sampling_rate() * _state->audio_desc.BlockAlign;
- _state->audio_desc.LinkedTrackID = 0;
- _state->audio_desc.ChannelFormat = ASDCP::PCM::CF_NONE;
-
- _state->frame_buffer.Capacity (ASDCP::PCM::CalcFrameBufferSize (_state->audio_desc));
- _state->frame_buffer.Size (ASDCP::PCM::CalcFrameBufferSize (_state->audio_desc));
- memset (_state->frame_buffer.Data(), 0, _state->frame_buffer.Capacity());
-
- _asset->fill_writer_info (&_state->writer_info);
-
- Kumu::Result_t r = _state->mxf_writer.OpenWrite (_asset->file().string().c_str(), _state->writer_info, _state->audio_desc);
- if (ASDCP_FAILURE (r)) {
- boost::throw_exception (FileError ("could not open audio MXF for writing", _asset->file().string(), r));
- }
-}
-
-void
-SoundMXFWriter::write (float const * const * data, int frames)
-{
- for (int i = 0; i < frames; ++i) {
-
- byte_t* out = _state->frame_buffer.Data() + _frame_buffer_offset;
-
- /* Write one sample per channel */
- for (int j = 0; j < _asset->channels(); ++j) {
- int32_t const s = data[j][i] * (1 << 23);
- *out++ = (s & 0xff);
- *out++ = (s & 0xff00) >> 8;
- *out++ = (s & 0xff0000) >> 16;
- }
- _frame_buffer_offset += 3 * _asset->channels();
-
- assert (_frame_buffer_offset <= int (_state->frame_buffer.Capacity()));
-
- /* Finish the MXF frame if required */
- if (_frame_buffer_offset == int (_state->frame_buffer.Capacity())) {
- write_current_frame ();
- _frame_buffer_offset = 0;
- memset (_state->frame_buffer.Data(), 0, _state->frame_buffer.Capacity());
- }
- }
-}
-
-void
-SoundMXFWriter::write_current_frame ()
-{
- ASDCP::Result_t const r = _state->mxf_writer.WriteFrame (_state->frame_buffer, _state->encryption_context, 0);
- if (ASDCP_FAILURE (r)) {
- boost::throw_exception (MiscError ("could not write audio MXF frame (" + lexical_cast<string> (int (r)) + ")"));
- }
-
- ++_frames_written;
-}
-
-void
-SoundMXFWriter::finalize ()
-{
- if (_frame_buffer_offset > 0) {
- write_current_frame ();
- }
-
- if (ASDCP_FAILURE (_state->mxf_writer.Finalize())) {
- boost::throw_exception (MiscError ("could not finalise audio MXF"));
- }
-
- _finalized = true;
- _asset->set_intrinsic_duration (_frames_written);
- _asset->set_duration (_frames_written);
+ return shared_ptr<SoundMXFWriter> (new SoundMXFWriter (this, file, standard));
}
string
diff --git a/src/sound_mxf.h b/src/sound_mxf.h
index 4216accb..098680ac 100644
--- a/src/sound_mxf.h
+++ b/src/sound_mxf.h
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2012 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -17,12 +17,8 @@
*/
-#ifndef LIBDCP_SOUND_ASSET_H
-#define LIBDCP_SOUND_ASSET_H
-
-/** @file src/sound_asset.h
- * @brief An asset made up of PCM audio data files
- */
+#ifndef LIBDCP_SOUND_MXF_H
+#define LIBDCP_SOUND_MXF_H
#include "mxf.h"
#include "types.h"
@@ -32,45 +28,15 @@ namespace dcp
{
class SoundFrame;
-class SoundMXF;
-
-class SoundMXFWriter
-{
-public:
- void write (float const * const *, int);
- void finalize ();
-
-private:
- friend class SoundMXF;
-
- SoundMXFWriter (SoundMXF *);
-
- /* no copy construction */
- SoundMXFWriter (SoundMXFWriter const &);
- SoundMXFWriter& operator= (SoundMXFWriter const &);
-
- void write_current_frame ();
-
- /* do this with an opaque pointer so we don't have to include
- ASDCP headers
- */
-
- struct ASDCPState;
- boost::shared_ptr<ASDCPState> _state;
-
- SoundMXF* _asset;
- bool _finalized;
- int _frames_written;
- int _frame_buffer_offset;
-};
+class SoundMXFWriter;
-/** @brief An asset made up of WAV files */
class SoundMXF : public MXF
{
public:
SoundMXF (boost::filesystem::path file);
+ SoundMXF (Fraction edit_rate, int sampling_rate, int channels);
- boost::shared_ptr<SoundMXFWriter> start_write ();
+ boost::shared_ptr<SoundMXFWriter> start_write (boost::filesystem::path file, Standard standard);
bool equals (boost::shared_ptr<const Content> other, EqualityOptions opt, boost::function<void (NoteType, std::string)> note) const;
@@ -94,7 +60,6 @@ public:
private:
std::string key_type () const;
- std::string cpl_node_name () const;
/** Number of channels in the asset */
int _channels;
diff --git a/src/sound_mxf_writer.cc b/src/sound_mxf_writer.cc
new file mode 100644
index 00000000..5dcd6791
--- /dev/null
+++ b/src/sound_mxf_writer.cc
@@ -0,0 +1,122 @@
+/*
+ Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
+
+ This program 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.
+
+ This program 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 this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#include "sound_mxf_writer.h"
+#include "sound_mxf.h"
+#include "exceptions.h"
+#include "compose.hpp"
+#include "AS_DCP.h"
+#include <boost/lexical_cast.hpp>
+
+using boost::lexical_cast;
+using namespace dcp;
+
+struct SoundMXFWriter::ASDCPState
+{
+ ASDCP::PCM::MXFWriter mxf_writer;
+ ASDCP::PCM::FrameBuffer frame_buffer;
+ ASDCP::WriterInfo writer_info;
+ ASDCP::PCM::AudioDescriptor audio_desc;
+ ASDCP::AESEncContext* encryption_context;
+};
+
+SoundMXFWriter::SoundMXFWriter (SoundMXF* m, boost::filesystem::path file, Standard standard)
+ : MXFWriter (m, file)
+ , _state (new SoundMXFWriter::ASDCPState)
+ , _sound_mxf (m)
+ , _frame_buffer_offset (0)
+{
+ _state->encryption_context = m->encryption_context ();
+
+ /* Derived from ASDCP::Wav::SimpleWaveHeader::FillADesc */
+ _state->audio_desc.EditRate = ASDCP::Rational (_sound_mxf->edit_rate().numerator, _sound_mxf->edit_rate().denominator);
+ _state->audio_desc.AudioSamplingRate = ASDCP::Rational (_sound_mxf->sampling_rate(), 1);
+ _state->audio_desc.Locked = 0;
+ _state->audio_desc.ChannelCount = _sound_mxf->channels ();
+ _state->audio_desc.QuantizationBits = 24;
+ _state->audio_desc.BlockAlign = 3 * _sound_mxf->channels();
+ _state->audio_desc.AvgBps = _sound_mxf->sampling_rate() * _state->audio_desc.BlockAlign;
+ _state->audio_desc.LinkedTrackID = 0;
+ _state->audio_desc.ChannelFormat = ASDCP::PCM::CF_NONE;
+
+ _state->frame_buffer.Capacity (ASDCP::PCM::CalcFrameBufferSize (_state->audio_desc));
+ _state->frame_buffer.Size (ASDCP::PCM::CalcFrameBufferSize (_state->audio_desc));
+ memset (_state->frame_buffer.Data(), 0, _state->frame_buffer.Capacity());
+
+ _sound_mxf->fill_writer_info (&_state->writer_info, standard);
+
+ Kumu::Result_t r = _state->mxf_writer.OpenWrite (file.string().c_str(), _state->writer_info, _state->audio_desc);
+ if (ASDCP_FAILURE (r)) {
+ boost::throw_exception (FileError ("could not open audio MXF for writing", file.string(), r));
+ }
+}
+
+void
+SoundMXFWriter::write (float const * const * data, int frames)
+{
+ assert (!_finalized);
+
+ for (int i = 0; i < frames; ++i) {
+
+ byte_t* out = _state->frame_buffer.Data() + _frame_buffer_offset;
+
+ /* Write one sample per channel */
+ for (int j = 0; j < _sound_mxf->channels(); ++j) {
+ int32_t const s = data[j][i] * (1 << 23);
+ *out++ = (s & 0xff);
+ *out++ = (s & 0xff00) >> 8;
+ *out++ = (s & 0xff0000) >> 16;
+ }
+ _frame_buffer_offset += 3 * _sound_mxf->channels();
+
+ assert (_frame_buffer_offset <= int (_state->frame_buffer.Capacity()));
+
+ /* Finish the MXF frame if required */
+ if (_frame_buffer_offset == int (_state->frame_buffer.Capacity())) {
+ write_current_frame ();
+ _frame_buffer_offset = 0;
+ memset (_state->frame_buffer.Data(), 0, _state->frame_buffer.Capacity());
+ }
+ }
+}
+
+void
+SoundMXFWriter::write_current_frame ()
+{
+ ASDCP::Result_t const r = _state->mxf_writer.WriteFrame (_state->frame_buffer, _state->encryption_context, 0);
+ if (ASDCP_FAILURE (r)) {
+ boost::throw_exception (MiscError (String::compose ("could not write audio MXF frame (%1)", int (r))));
+ }
+
+ ++_frames_written;
+}
+
+void
+SoundMXFWriter::finalize ()
+{
+ if (_frame_buffer_offset > 0) {
+ write_current_frame ();
+ }
+
+ if (ASDCP_FAILURE (_state->mxf_writer.Finalize())) {
+ boost::throw_exception (MiscError ("could not finalise audio MXF"));
+ }
+
+ MXFWriter::finalize ();
+}
diff --git a/src/sound_mxf_writer.h b/src/sound_mxf_writer.h
new file mode 100644
index 00000000..4f60074c
--- /dev/null
+++ b/src/sound_mxf_writer.h
@@ -0,0 +1,55 @@
+/*
+ Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
+
+ This program 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.
+
+ This program 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 this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#include "mxf_writer.h"
+#include "types.h"
+#include <boost/shared_ptr.hpp>
+#include <boost/filesystem.hpp>
+
+namespace dcp {
+
+class SoundFrame;
+class SoundMXF;
+
+class SoundMXFWriter : public MXFWriter
+{
+public:
+ void write (float const * const *, int);
+ void finalize ();
+
+private:
+ friend class SoundMXF;
+
+ SoundMXFWriter (SoundMXF *, boost::filesystem::path, Standard standard);
+
+ void write_current_frame ();
+
+ /* do this with an opaque pointer so we don't have to include
+ ASDCP headers
+ */
+
+ struct ASDCPState;
+ boost::shared_ptr<ASDCPState> _state;
+
+ SoundMXF* _sound_mxf;
+ int _frame_buffer_offset;
+};
+
+}
+
diff --git a/src/stereo_picture_frame.cc b/src/stereo_picture_frame.cc
index 893a9f72..790fcc1a 100644
--- a/src/stereo_picture_frame.cc
+++ b/src/stereo_picture_frame.cc
@@ -63,6 +63,8 @@ StereoPictureFrame::~StereoPictureFrame ()
* @param reduce a factor by which to reduce the resolution
* of the image, expressed as a power of two (pass 0 for no
* reduction).
+ * @param srgb_gamma Reciprocal of gamma to use when doing the
+ * output gamma correction (after conversion from XYZ to RGB).
*
* @return An ARGB representation of one of the eyes (left or right)
* of this frame. This is ARGB in the Cairo sense, so that each
diff --git a/src/stereo_picture_mxf.cc b/src/stereo_picture_mxf.cc
index 7e112687..980c6ad5 100644
--- a/src/stereo_picture_mxf.cc
+++ b/src/stereo_picture_mxf.cc
@@ -30,6 +30,48 @@ using boost::shared_ptr;
using boost::dynamic_pointer_cast;
using namespace dcp;
+StereoPictureMXF::StereoPictureMXF (boost::filesystem::path file)
+ : PictureMXF (file)
+{
+ ASDCP::JP2K::MXFSReader reader;
+ Kumu::Result_t r = reader.OpenRead (file.string().c_str());
+ if (ASDCP_FAILURE (r)) {
+ boost::throw_exception (MXFFileError ("could not open MXF file for reading", file.string(), r));
+ }
+
+ ASDCP::JP2K::PictureDescriptor desc;
+ if (ASDCP_FAILURE (reader.FillPictureDescriptor (desc))) {
+ boost::throw_exception (DCPReadError ("could not read video MXF information"));
+ }
+
+ read_picture_descriptor (desc);
+}
+
+StereoPictureMXF::StereoPictureMXF (Fraction edit_rate)
+ : PictureMXF
+ (edit_rate)
+{
+
+}
+
+shared_ptr<const StereoPictureFrame>
+StereoPictureMXF::get_frame (int n) const
+{
+ return shared_ptr<const StereoPictureFrame> (new StereoPictureFrame (file().string(), n));
+}
+
+shared_ptr<PictureMXFWriter>
+StereoPictureMXF::start_write (boost::filesystem::path file, Standard standard, bool overwrite)
+{
+ return shared_ptr<StereoPictureMXFWriter> (new StereoPictureMXFWriter (this, file, standard, overwrite));
+}
+
+int
+StereoPictureMXF::edit_rate_factor () const
+{
+ return 2;
+}
+
bool
StereoPictureMXF::equals (shared_ptr<const Content> other, EqualityOptions opt, boost::function<void (NoteType, string)> note) const
{
@@ -88,57 +130,3 @@ StereoPictureMXF::equals (shared_ptr<const Content> other, EqualityOptions opt,
return true;
}
-
-StereoPictureMXF::StereoPictureMXF (boost::filesystem::path file)
- : PictureMXF (file)
-{
- ASDCP::JP2K::MXFSReader reader;
- Kumu::Result_t r = reader.OpenRead (file.string().c_str());
- if (ASDCP_FAILURE (r)) {
- boost::throw_exception (MXFFileError ("could not open MXF file for reading", file.string(), r));
- }
-
- ASDCP::JP2K::PictureDescriptor desc;
- if (ASDCP_FAILURE (reader.FillPictureDescriptor (desc))) {
- boost::throw_exception (DCPReadError ("could not read video MXF information"));
- }
-
- _size.width = desc.StoredWidth;
- _size.height = desc.StoredHeight;
-}
-
-shared_ptr<const StereoPictureFrame>
-StereoPictureMXF::get_frame (int n) const
-{
- return shared_ptr<const StereoPictureFrame> (new StereoPictureFrame (file().string(), n));
-}
-
-shared_ptr<PictureMXFWriter>
-StereoPictureMXF::start_write (boost::filesystem::path file, bool overwrite)
-{
- return shared_ptr<StereoPictureMXFWriter> (new StereoPictureMXFWriter (this, file, overwrite));
-}
-
-string
-StereoPictureMXF::cpl_node_name () const
-{
- return "msp-cpl:MainStereoscopicPicture";
-}
-
-pair<string, string>
-StereoPictureMXF::cpl_node_attribute () const
-{
- if (_interop) {
- return make_pair ("xmlns:msp-cpl", "http://www.digicine.com/schemas/437-Y/2007/Main-Stereo-Picture-CPL");
- } else {
- return make_pair ("xmlns:msp-cpl", "http://www.smpte-ra.org/schemas/429-10/2008/Main-Stereo-Picture-CPL");
- }
-
- return make_pair ("", "");
-}
-
-int
-StereoPictureMXF::edit_rate_factor () const
-{
- return 2;
-}
diff --git a/src/stereo_picture_mxf.h b/src/stereo_picture_mxf.h
index 4af8a327..eb527a1e 100644
--- a/src/stereo_picture_mxf.h
+++ b/src/stereo_picture_mxf.h
@@ -29,16 +29,15 @@ class StereoPictureMXF : public PictureMXF
{
public:
StereoPictureMXF (boost::filesystem::path file);
+ StereoPictureMXF (Fraction edit_rate);
/** Start a progressive write to a StereoPictureMXF */
- boost::shared_ptr<PictureMXFWriter> start_write (boost::filesystem::path file, bool);
+ boost::shared_ptr<PictureMXFWriter> start_write (boost::filesystem::path file, Standard, bool);
boost::shared_ptr<const StereoPictureFrame> get_frame (int n) const;
bool equals (boost::shared_ptr<const Content> other, EqualityOptions opt, boost::function<void (NoteType, std::string)> note) const;
private:
- std::string cpl_node_name () const;
- std::pair<std::string, std::string> cpl_node_attribute () const;
int edit_rate_factor () const;
};
diff --git a/src/stereo_picture_mxf_writer.cc b/src/stereo_picture_mxf_writer.cc
index ad029b57..4ea65e05 100644
--- a/src/stereo_picture_mxf_writer.cc
+++ b/src/stereo_picture_mxf_writer.cc
@@ -36,8 +36,8 @@ struct StereoPictureMXFWriter::ASDCPState : public ASDCPStateBase
ASDCP::JP2K::MXFSWriter mxf_writer;
};
-StereoPictureMXFWriter::StereoPictureMXFWriter (PictureMXF* mxf, boost::filesystem::path file, bool overwrite)
- : PictureMXFWriter (mxf, file, overwrite)
+StereoPictureMXFWriter::StereoPictureMXFWriter (PictureMXF* mxf, boost::filesystem::path file, Standard standard, bool overwrite)
+ : PictureMXFWriter (mxf, file, standard, overwrite)
, _state (new StereoPictureMXFWriter::ASDCPState)
, _next_eye (EYE_LEFT)
{
@@ -47,7 +47,7 @@ StereoPictureMXFWriter::StereoPictureMXFWriter (PictureMXF* mxf, boost::filesyst
void
StereoPictureMXFWriter::start (uint8_t* data, int size)
{
- dcp::start (this, _state, _mxf, data, size);
+ dcp::start (this, _state, _standard, _picture_mxf, data, size);
}
/** Write a frame for one eye. Frames must be written left, then right, then left etc.
@@ -84,7 +84,10 @@ StereoPictureMXFWriter::write (uint8_t* data, int size)
_next_eye = _next_eye == EYE_LEFT ? EYE_RIGHT : EYE_LEFT;
- ++_frames_written;
+ if (_next_eye == EYE_LEFT) {
+ ++_frames_written;
+ }
+
return FrameInfo (before_offset, _state->mxf_writer.Tell() - before_offset, hash);
}
@@ -100,20 +103,18 @@ StereoPictureMXFWriter::fake_write (int size)
}
_next_eye = _next_eye == EYE_LEFT ? EYE_RIGHT : EYE_LEFT;
- ++_frames_written;
+ if (_next_eye == EYE_LEFT) {
+ ++_frames_written;
+ }
}
void
StereoPictureMXFWriter::finalize ()
{
- assert (!_finalized);
-
Kumu::Result_t r = _state->mxf_writer.Finalize();
if (ASDCP_FAILURE (r)) {
boost::throw_exception (MXFFileError ("error in finalizing video MXF", _mxf->file().string(), r));
}
- _finalized = true;
- _mxf->set_intrinsic_duration (_frames_written / 2);
- _mxf->set_duration (_frames_written / 2);
+ PictureMXFWriter::finalize ();
}
diff --git a/src/stereo_picture_mxf_writer.h b/src/stereo_picture_mxf_writer.h
index a34af069..8773eccd 100644
--- a/src/stereo_picture_mxf_writer.h
+++ b/src/stereo_picture_mxf_writer.h
@@ -17,12 +17,13 @@
*/
+#include "picture_mxf_writer.h"
+#include "types.h"
+#include <boost/shared_ptr.hpp>
+#include <boost/utility.hpp>
#include <stdint.h>
#include <string>
#include <fstream>
-#include <boost/shared_ptr.hpp>
-#include <boost/utility.hpp>
-#include "picture_mxf_writer.h"
namespace dcp {
@@ -46,7 +47,7 @@ public:
private:
friend class StereoPictureMXF;
- StereoPictureMXFWriter (PictureMXF *, boost::filesystem::path file, bool);
+ StereoPictureMXFWriter (PictureMXF *, boost::filesystem::path file, Standard, bool);
void start (uint8_t *, int);
/* do this with an opaque pointer so we don't have to include
diff --git a/src/subtitle.cc b/src/subtitle.cc
new file mode 100644
index 00000000..dc7a6b22
--- /dev/null
+++ b/src/subtitle.cc
@@ -0,0 +1,60 @@
+/*
+ Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
+
+ This program 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.
+
+ This program 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 this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#include "subtitle.h"
+#include "xml.h"
+#include "font.h"
+#include "text.h"
+#include <libcxml/cxml.h>
+
+using std::string;
+using boost::shared_ptr;
+using boost::lexical_cast;
+using namespace dcp;
+
+Subtitle::Subtitle (shared_ptr<const cxml::Node> node)
+{
+ in = Time (node->string_attribute ("TimeIn"));
+ out = Time (node->string_attribute ("TimeOut"));
+ font_nodes = type_children<Font> (node, "Font");
+ text_nodes = type_children<Text> (node, "Text");
+ fade_up_time = fade_time (node, "FadeUpTime");
+ fade_down_time = fade_time (node, "FadeDownTime");
+}
+
+Time
+Subtitle::fade_time (shared_ptr<const cxml::Node> node, string name)
+{
+ string const u = node->optional_string_attribute (name).get_value_or ("");
+ Time t;
+
+ if (u.empty ()) {
+ t = Time (0, 0, 0, 20);
+ } else if (u.find (":") != string::npos) {
+ t = Time (u);
+ } else {
+ t = Time (0, 0, 0, lexical_cast<int> (u));
+ }
+
+ if (t > Time (0, 0, 8, 0)) {
+ t = Time (0, 0, 8, 0);
+ }
+
+ return t;
+}
diff --git a/src/subtitle.h b/src/subtitle.h
new file mode 100644
index 00000000..073bfb0c
--- /dev/null
+++ b/src/subtitle.h
@@ -0,0 +1,55 @@
+/*
+ Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
+
+ This program 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.
+
+ This program 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 this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#ifndef LIBDCP_SUBTITLE_H
+#define LIBDCP_SUBTITLE_H
+
+#include "dcp_time.h"
+#include <boost/shared_ptr.hpp>
+#include <list>
+
+namespace cxml {
+ class Node;
+}
+
+namespace dcp {
+
+class Font;
+class Text;
+
+class Subtitle
+{
+public:
+ Subtitle () {}
+ Subtitle (boost::shared_ptr<const cxml::Node> node);
+
+ Time in;
+ Time out;
+ Time fade_up_time;
+ Time fade_down_time;
+ std::list<boost::shared_ptr<Font> > font_nodes;
+ std::list<boost::shared_ptr<Text> > text_nodes;
+
+private:
+ Time fade_time (boost::shared_ptr<const cxml::Node>, std::string name);
+};
+
+}
+
+#endif
diff --git a/src/subtitle_asset.h b/src/subtitle_asset.h
deleted file mode 100644
index cbd3ad58..00000000
--- a/src/subtitle_asset.h
+++ /dev/null
@@ -1,198 +0,0 @@
-/*
- Copyright (C) 2012 Carl Hetherington <cth@carlh.net>
-
- This program 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.
-
- This program 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 this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-*/
-
-#ifndef LIBDCP_SUBTITLE_ASSET_H
-#define LIBDCP_SUBTITLE_ASSET_H
-
-#include <libcxml/cxml.h>
-#include "content.h"
-#include "dcp_time.h"
-
-namespace dcp
-{
-
-namespace parse
-{
- class Font;
- class Text;
- class Subtitle;
- class LoadFont;
-}
-
-class Subtitle
-{
-public:
- Subtitle (
- std::string font,
- bool italic,
- Color color,
- int size,
- Time in,
- Time out,
- float v_position,
- VAlign v_align,
- std::string text,
- Effect effect,
- Color effect_color,
- Time fade_up_time,
- Time fade_down_time
- );
-
- std::string font () const {
- return _font;
- }
-
- bool italic () const {
- return _italic;
- }
-
- Color color () const {
- return _color;
- }
-
- Time in () const {
- return _in;
- }
-
- Time out () const {
- return _out;
- }
-
- std::string text () const {
- return _text;
- }
-
- float v_position () const {
- return _v_position;
- }
-
- VAlign v_align () const {
- return _v_align;
- }
-
- Effect effect () const {
- return _effect;
- }
-
- Color effect_color () const {
- return _effect_color;
- }
-
- Time fade_up_time () const {
- return _fade_up_time;
- }
-
- Time fade_down_time () const {
- return _fade_down_time;
- }
-
- int size () const {
- return _size;
- }
-
- int size_in_pixels (int screen_height) const;
-
-private:
- std::string _font;
- bool _italic;
- Color _color;
- /** Size in points as if the screen height is 11 inches, so a 72pt font
- * would be 1/11th of the screen height.
- */
- int _size;
- Time _in;
- Time _out;
- /** Vertical position as a proportion of the screen height from the top
- * (between 0 and 1)
- */
- float _v_position;
- VAlign _v_align;
- std::string _text;
- Effect _effect;
- Color _effect_color;
- Time _fade_up_time;
- Time _fade_down_time;
-};
-
-bool operator== (Subtitle const & a, Subtitle const & b);
-std::ostream& operator<< (std::ostream& s, Subtitle const & sub);
-
-class SubtitleAsset : public Content
-{
-public:
- SubtitleAsset (boost::filesystem::path file);
- SubtitleAsset (std::string directory, std::string movie_title, std::string language);
-
- void write_to_cpl (xmlpp::Element *) const;
- virtual bool equals (boost::shared_ptr<const Content>, EqualityOptions, boost::function<void (NoteType, std::string)> note) const {
- /* XXX */
- note (ERROR, "subtitle assets not compared yet");
- return true;
- }
-
- std::string language () const {
- return _language;
- }
-
- std::list<boost::shared_ptr<Subtitle> > subtitles_at (Time t) const;
- std::list<boost::shared_ptr<Subtitle> > const & subtitles () const {
- return _subtitles;
- }
-
- void add (boost::shared_ptr<Subtitle>);
-
- void write_xml () const;
- Glib::ustring xml_as_string () const;
-
-private:
- std::string font_id_to_name (std::string id) const;
-
- struct ParseState {
- std::list<boost::shared_ptr<parse::Font> > font_nodes;
- std::list<boost::shared_ptr<parse::Text> > text_nodes;
- std::list<boost::shared_ptr<parse::Subtitle> > subtitle_nodes;
- };
-
- void maybe_add_subtitle (std::string text, ParseState const & parse_state);
-
- void examine_font_nodes (
- boost::shared_ptr<const cxml::Node> xml,
- std::list<boost::shared_ptr<parse::Font> > const & font_nodes,
- ParseState& parse_state
- );
-
- void examine_text_nodes (
- boost::shared_ptr<const cxml::Node> xml,
- std::list<boost::shared_ptr<parse::Text> > const & text_nodes,
- ParseState& parse_state
- );
-
- std::string _movie_title;
- /* strangely, this is sometimes a string */
- std::string _reel_number;
- std::string _language;
- std::list<boost::shared_ptr<parse::LoadFont> > _load_font_nodes;
-
- std::list<boost::shared_ptr<Subtitle> > _subtitles;
- bool _need_sort;
-};
-
-}
-
-#endif
diff --git a/src/subtitle_asset.cc b/src/subtitle_content.cc
index 1c36fdfc..e32118c4 100644
--- a/src/subtitle_asset.cc
+++ b/src/subtitle_content.cc
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2012 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -17,14 +17,17 @@
*/
-#include <fstream>
-#include <boost/lexical_cast.hpp>
-#include <boost/algorithm/string.hpp>
-#include <libxml++/nodes/element.h>
-#include "subtitle_asset.h"
-#include "parse/subtitle.h"
+#include "subtitle_content.h"
#include "util.h"
#include "xml.h"
+#include "font.h"
+#include "text.h"
+#include "load_font.h"
+#include "subtitle_string.h"
+#include <libxml++/nodes/element.h>
+#include <boost/lexical_cast.hpp>
+#include <boost/algorithm/string.hpp>
+#include <fstream>
using std::string;
using std::list;
@@ -36,7 +39,7 @@ using boost::lexical_cast;
using boost::optional;
using namespace dcp;
-SubtitleAsset::SubtitleAsset (boost::filesystem::path file)
+SubtitleContent::SubtitleContent (boost::filesystem::path file)
: Content (file)
, _need_sort (false)
{
@@ -50,8 +53,8 @@ SubtitleAsset::SubtitleAsset (boost::filesystem::path file)
xml->ignore_child ("LoadFont");
- list<shared_ptr<dcp::parse::Font> > font_nodes = type_children<dcp::parse::Font> (xml, "Font");
- _load_font_nodes = type_children<dcp::parse::LoadFont> (xml, "LoadFont");
+ list<shared_ptr<dcp::Font> > font_nodes = type_children<dcp::Font> (xml, "Font");
+ _load_font_nodes = type_children<dcp::LoadFont> (xml, "LoadFont");
/* Now make Subtitle objects to represent the raw XML nodes
in a sane way.
@@ -61,8 +64,8 @@ SubtitleAsset::SubtitleAsset (boost::filesystem::path file)
examine_font_nodes (xml, font_nodes, parse_state);
}
-SubtitleAsset::SubtitleAsset (string directory, string movie_title, string language)
- : Content (directory)
+SubtitleContent::SubtitleContent (Fraction edit_rate, string movie_title, string language)
+ : Content (edit_rate)
, _movie_title (movie_title)
, _reel_number ("1")
, _language (language)
@@ -72,18 +75,18 @@ SubtitleAsset::SubtitleAsset (string directory, string movie_title, string langu
}
void
-SubtitleAsset::examine_font_nodes (
+SubtitleContent::examine_font_nodes (
shared_ptr<const cxml::Node> xml,
- list<shared_ptr<dcp::parse::Font> > const & font_nodes,
+ list<shared_ptr<dcp::Font> > const & font_nodes,
ParseState& parse_state
)
{
- for (list<shared_ptr<dcp::parse::Font> >::const_iterator i = font_nodes.begin(); i != font_nodes.end(); ++i) {
+ for (list<shared_ptr<dcp::Font> >::const_iterator i = font_nodes.begin(); i != font_nodes.end(); ++i) {
parse_state.font_nodes.push_back (*i);
maybe_add_subtitle ((*i)->text, parse_state);
- for (list<shared_ptr<dcp::parse::Subtitle> >::iterator j = (*i)->subtitle_nodes.begin(); j != (*i)->subtitle_nodes.end(); ++j) {
+ for (list<shared_ptr<dcp::Subtitle> >::iterator j = (*i)->subtitle_nodes.begin(); j != (*i)->subtitle_nodes.end(); ++j) {
parse_state.subtitle_nodes.push_back (*j);
examine_text_nodes (xml, (*j)->text_nodes, parse_state);
examine_font_nodes (xml, (*j)->font_nodes, parse_state);
@@ -98,13 +101,13 @@ SubtitleAsset::examine_font_nodes (
}
void
-SubtitleAsset::examine_text_nodes (
+SubtitleContent::examine_text_nodes (
shared_ptr<const cxml::Node> xml,
- list<shared_ptr<dcp::parse::Text> > const & text_nodes,
+ list<shared_ptr<dcp::Text> > const & text_nodes,
ParseState& parse_state
)
{
- for (list<shared_ptr<dcp::parse::Text> >::const_iterator i = text_nodes.begin(); i != text_nodes.end(); ++i) {
+ for (list<shared_ptr<dcp::Text> >::const_iterator i = text_nodes.begin(); i != text_nodes.end(); ++i) {
parse_state.text_nodes.push_back (*i);
maybe_add_subtitle ((*i)->text, parse_state);
examine_font_nodes (xml, (*i)->font_nodes, parse_state);
@@ -113,7 +116,7 @@ SubtitleAsset::examine_text_nodes (
}
void
-SubtitleAsset::maybe_add_subtitle (string text, ParseState const & parse_state)
+SubtitleContent::maybe_add_subtitle (string text, ParseState const & parse_state)
{
if (empty_or_white_space (text)) {
return;
@@ -126,13 +129,13 @@ SubtitleAsset::maybe_add_subtitle (string text, ParseState const & parse_state)
assert (!parse_state.text_nodes.empty ());
assert (!parse_state.subtitle_nodes.empty ());
- dcp::parse::Font effective_font (parse_state.font_nodes);
- dcp::parse::Text effective_text (*parse_state.text_nodes.back ());
- dcp::parse::Subtitle effective_subtitle (*parse_state.subtitle_nodes.back ());
+ dcp::Font effective_font (parse_state.font_nodes);
+ dcp::Text effective_text (*parse_state.text_nodes.back ());
+ dcp::Subtitle effective_subtitle (*parse_state.subtitle_nodes.back ());
_subtitles.push_back (
- shared_ptr<Subtitle> (
- new Subtitle (
+ shared_ptr<SubtitleString> (
+ new SubtitleString (
font_id_to_name (effective_font.id),
effective_font.italic.get(),
effective_font.color.get(),
@@ -151,11 +154,11 @@ SubtitleAsset::maybe_add_subtitle (string text, ParseState const & parse_state)
);
}
-list<shared_ptr<Subtitle> >
-SubtitleAsset::subtitles_at (Time t) const
+list<shared_ptr<SubtitleString> >
+SubtitleContent::subtitles_at (Time t) const
{
- list<shared_ptr<Subtitle> > s;
- for (list<shared_ptr<Subtitle> >::const_iterator i = _subtitles.begin(); i != _subtitles.end(); ++i) {
+ list<shared_ptr<SubtitleString> > s;
+ for (list<shared_ptr<SubtitleString> >::const_iterator i = _subtitles.begin(); i != _subtitles.end(); ++i) {
if ((*i)->in() <= t && t <= (*i)->out ()) {
s.push_back (*i);
}
@@ -165,9 +168,9 @@ SubtitleAsset::subtitles_at (Time t) const
}
std::string
-SubtitleAsset::font_id_to_name (string id) const
+SubtitleContent::font_id_to_name (string id) const
{
- list<shared_ptr<dcp::parse::LoadFont> >::const_iterator i = _load_font_nodes.begin();
+ list<shared_ptr<dcp::LoadFont> >::const_iterator i = _load_font_nodes.begin();
while (i != _load_font_nodes.end() && (*i)->id != id) {
++i;
}
@@ -183,109 +186,15 @@ SubtitleAsset::font_id_to_name (string id) const
return "";
}
-Subtitle::Subtitle (
- string font,
- bool italic,
- Color color,
- int size,
- Time in,
- Time out,
- float v_position,
- VAlign v_align,
- string text,
- Effect effect,
- Color effect_color,
- Time fade_up_time,
- Time fade_down_time
- )
- : _font (font)
- , _italic (italic)
- , _color (color)
- , _size (size)
- , _in (in)
- , _out (out)
- , _v_position (v_position)
- , _v_align (v_align)
- , _text (text)
- , _effect (effect)
- , _effect_color (effect_color)
- , _fade_up_time (fade_up_time)
- , _fade_down_time (fade_down_time)
-{
-
-}
-
-int
-Subtitle::size_in_pixels (int screen_height) const
-{
- /* Size in the subtitle file is given in points as if the screen
- height is 11 inches, so a 72pt font would be 1/11th of the screen
- height.
- */
-
- return _size * screen_height / (11 * 72);
-}
-
-bool
-dcp::operator== (Subtitle const & a, Subtitle const & b)
-{
- return (
- a.font() == b.font() &&
- a.italic() == b.italic() &&
- a.color() == b.color() &&
- a.size() == b.size() &&
- a.in() == b.in() &&
- a.out() == b.out() &&
- a.v_position() == b.v_position() &&
- a.v_align() == b.v_align() &&
- a.text() == b.text() &&
- a.effect() == b.effect() &&
- a.effect_color() == b.effect_color() &&
- a.fade_up_time() == b.fade_up_time() &&
- a.fade_down_time() == b.fade_down_time()
- );
-}
-
-ostream&
-dcp::operator<< (ostream& s, Subtitle const & sub)
-{
- s << "\n`" << sub.text() << "' from " << sub.in() << " to " << sub.out() << ";\n"
- << "fade up " << sub.fade_up_time() << ", fade down " << sub.fade_down_time() << ";\n"
- << "font " << sub.font() << ", ";
-
- if (sub.italic()) {
- s << "italic";
- } else {
- s << "non-italic";
- }
-
- s << ", size " << sub.size() << ", color " << sub.color() << ", vpos " << sub.v_position() << ", valign " << ((int) sub.v_align()) << ";\n"
- << "effect " << ((int) sub.effect()) << ", effect color " << sub.effect_color();
-
- return s;
-}
-
void
-SubtitleAsset::add (shared_ptr<Subtitle> s)
+SubtitleContent::add (shared_ptr<SubtitleString> s)
{
_subtitles.push_back (s);
_need_sort = true;
}
-void
-SubtitleAsset::write_to_cpl (xmlpp::Element* node) const
-{
- /* XXX: should EditRate, Duration and IntrinsicDuration be in here? */
-
- xmlpp::Node* ms = node->add_child ("MainSubtitle");
- ms->add_child("Id")->add_child_text("urn:uuid:" + _id);
- ms->add_child("AnnotationText")->add_child_text (_file.string ());
- /* XXX */
- ms->add_child("EntryPoint")->add_child_text ("0");
-}
-
struct SubtitleSorter {
- bool operator() (shared_ptr<Subtitle> a, shared_ptr<Subtitle> b) {
+ bool operator() (shared_ptr<SubtitleString> a, shared_ptr<SubtitleString> b) {
if (a->in() != b->in()) {
return a->in() < b->in();
}
@@ -294,7 +203,7 @@ struct SubtitleSorter {
};
void
-SubtitleAsset::write_xml () const
+SubtitleContent::write_xml () const
{
FILE* f = fopen_boost (file (), "r");
Glib::ustring const s = xml_as_string ();
@@ -303,7 +212,7 @@ SubtitleAsset::write_xml () const
}
Glib::ustring
-SubtitleAsset::xml_as_string () const
+SubtitleContent::xml_as_string () const
{
xmlpp::Document doc;
xmlpp::Element* root = doc.create_root_node ("DCSubtitle");
@@ -324,7 +233,7 @@ SubtitleAsset::xml_as_string () const
load_font->set_attribute("URI", _load_font_nodes.front()->uri);
}
- list<shared_ptr<Subtitle> > sorted = _subtitles;
+ list<shared_ptr<SubtitleString> > sorted = _subtitles;
if (_need_sort) {
sorted.sort (SubtitleSorter ());
}
@@ -346,7 +255,7 @@ SubtitleAsset::xml_as_string () const
xmlpp::Element* font = 0;
xmlpp::Element* subtitle = 0;
- for (list<shared_ptr<Subtitle> >::iterator i = sorted.begin(); i != sorted.end(); ++i) {
+ for (list<shared_ptr<SubtitleString> >::iterator i = sorted.begin(); i != sorted.end(); ++i) {
/* We will start a new <Font>...</Font> whenever some font property changes.
I suppose we should really make an optimal hierarchy of <Font> tags, but
diff --git a/src/subtitle_content.h b/src/subtitle_content.h
new file mode 100644
index 00000000..b8db0c2c
--- /dev/null
+++ b/src/subtitle_content.h
@@ -0,0 +1,104 @@
+/*
+ Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
+
+ This program 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.
+
+ This program 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 this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#ifndef LIBDCP_SUBTITLE_CONTENT_H
+#define LIBDCP_SUBTITLE_CONTENT_H
+
+#include "content.h"
+#include "dcp_time.h"
+#include <libcxml/cxml.h>
+
+namespace dcp
+{
+
+class SubtitleString;
+class Font;
+class Text;
+class Subtitle;
+class LoadFont;
+
+/** @class SubtitleContent
+ * @brief A representation of an XML file containing subtitles.
+ */
+class SubtitleContent : public Content
+{
+public:
+ SubtitleContent (boost::filesystem::path file);
+ SubtitleContent (Fraction edit_rate, std::string movie_title, std::string language);
+
+ std::string pkl_type () const {
+ return "text/xml";
+ }
+
+ virtual bool equals (boost::shared_ptr<const Content>, EqualityOptions, boost::function<void (NoteType, std::string)> note) const {
+ /* XXX */
+ note (ERROR, "subtitle content not compared yet");
+ return true;
+ }
+
+ std::string language () const {
+ return _language;
+ }
+
+ std::list<boost::shared_ptr<SubtitleString> > subtitles_at (Time t) const;
+ std::list<boost::shared_ptr<SubtitleString> > const & subtitles () const {
+ return _subtitles;
+ }
+
+ void add (boost::shared_ptr<SubtitleString>);
+
+ void write_xml () const;
+ Glib::ustring xml_as_string () const;
+
+private:
+ std::string font_id_to_name (std::string id) const;
+
+ struct ParseState {
+ std::list<boost::shared_ptr<Font> > font_nodes;
+ std::list<boost::shared_ptr<Text> > text_nodes;
+ std::list<boost::shared_ptr<Subtitle> > subtitle_nodes;
+ };
+
+ void maybe_add_subtitle (std::string text, ParseState const & parse_state);
+
+ void examine_font_nodes (
+ boost::shared_ptr<const cxml::Node> xml,
+ std::list<boost::shared_ptr<Font> > const & font_nodes,
+ ParseState& parse_state
+ );
+
+ void examine_text_nodes (
+ boost::shared_ptr<const cxml::Node> xml,
+ std::list<boost::shared_ptr<Text> > const & text_nodes,
+ ParseState& parse_state
+ );
+
+ std::string _movie_title;
+ /* strangely, this is sometimes a string */
+ std::string _reel_number;
+ std::string _language;
+ std::list<boost::shared_ptr<LoadFont> > _load_font_nodes;
+
+ std::list<boost::shared_ptr<SubtitleString> > _subtitles;
+ bool _need_sort;
+};
+
+}
+
+#endif
diff --git a/src/subtitle_string.cc b/src/subtitle_string.cc
new file mode 100644
index 00000000..66869fd5
--- /dev/null
+++ b/src/subtitle_string.cc
@@ -0,0 +1,107 @@
+/*
+ Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
+
+ This program 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.
+
+ This program 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 this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#include "subtitle_string.h"
+#include "xml.h"
+
+using std::string;
+using std::ostream;
+using namespace dcp;
+
+SubtitleString::SubtitleString (
+ string font,
+ bool italic,
+ Color color,
+ int size,
+ Time in,
+ Time out,
+ float v_position,
+ VAlign v_align,
+ string text,
+ Effect effect,
+ Color effect_color,
+ Time fade_up_time,
+ Time fade_down_time
+ )
+ : _font (font)
+ , _italic (italic)
+ , _color (color)
+ , _size (size)
+ , _in (in)
+ , _out (out)
+ , _v_position (v_position)
+ , _v_align (v_align)
+ , _text (text)
+ , _effect (effect)
+ , _effect_color (effect_color)
+ , _fade_up_time (fade_up_time)
+ , _fade_down_time (fade_down_time)
+{
+
+}
+
+int
+SubtitleString::size_in_pixels (int screen_height) const
+{
+ /* Size in the subtitle file is given in points as if the screen
+ height is 11 inches, so a 72pt font would be 1/11th of the screen
+ height.
+ */
+
+ return _size * screen_height / (11 * 72);
+}
+
+bool
+dcp::operator== (SubtitleString const & a, SubtitleString const & b)
+{
+ return (
+ a.font() == b.font() &&
+ a.italic() == b.italic() &&
+ a.color() == b.color() &&
+ a.size() == b.size() &&
+ a.in() == b.in() &&
+ a.out() == b.out() &&
+ a.v_position() == b.v_position() &&
+ a.v_align() == b.v_align() &&
+ a.text() == b.text() &&
+ a.effect() == b.effect() &&
+ a.effect_color() == b.effect_color() &&
+ a.fade_up_time() == b.fade_up_time() &&
+ a.fade_down_time() == b.fade_down_time()
+ );
+}
+
+ostream&
+dcp::operator<< (ostream& s, SubtitleString const & sub)
+{
+ s << "\n`" << sub.text() << "' from " << sub.in() << " to " << sub.out() << ";\n"
+ << "fade up " << sub.fade_up_time() << ", fade down " << sub.fade_down_time() << ";\n"
+ << "font " << sub.font() << ", ";
+
+ if (sub.italic()) {
+ s << "italic";
+ } else {
+ s << "non-italic";
+ }
+
+ s << ", size " << sub.size() << ", color " << sub.color() << ", vpos " << sub.v_position() << ", valign " << ((int) sub.v_align()) << ";\n"
+ << "effect " << ((int) sub.effect()) << ", effect color " << sub.effect_color();
+
+ return s;
+}
diff --git a/src/subtitle_string.h b/src/subtitle_string.h
new file mode 100644
index 00000000..59131f07
--- /dev/null
+++ b/src/subtitle_string.h
@@ -0,0 +1,124 @@
+/*
+ Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
+
+ This program 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.
+
+ This program 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 this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#include "types.h"
+#include "dcp_time.h"
+#include <string>
+
+namespace dcp {
+
+class SubtitleString
+{
+public:
+ SubtitleString (
+ std::string font,
+ bool italic,
+ Color color,
+ int size,
+ Time in,
+ Time out,
+ float v_position,
+ VAlign v_align,
+ std::string text,
+ Effect effect,
+ Color effect_color,
+ Time fade_up_time,
+ Time fade_down_time
+ );
+
+ std::string font () const {
+ return _font;
+ }
+
+ bool italic () const {
+ return _italic;
+ }
+
+ Color color () const {
+ return _color;
+ }
+
+ Time in () const {
+ return _in;
+ }
+
+ Time out () const {
+ return _out;
+ }
+
+ std::string text () const {
+ return _text;
+ }
+
+ float v_position () const {
+ return _v_position;
+ }
+
+ VAlign v_align () const {
+ return _v_align;
+ }
+
+ Effect effect () const {
+ return _effect;
+ }
+
+ Color effect_color () const {
+ return _effect_color;
+ }
+
+ Time fade_up_time () const {
+ return _fade_up_time;
+ }
+
+ Time fade_down_time () const {
+ return _fade_down_time;
+ }
+
+ int size () const {
+ return _size;
+ }
+
+ int size_in_pixels (int screen_height) const;
+
+private:
+ std::string _font;
+ bool _italic;
+ Color _color;
+ /** Size in points as if the screen height is 11 inches, so a 72pt font
+ * would be 1/11th of the screen height.
+ */
+ int _size;
+ Time _in;
+ Time _out;
+ /** Vertical position as a proportion of the screen height from the top
+ * (between 0 and 1)
+ */
+ float _v_position;
+ VAlign _v_align;
+ std::string _text;
+ Effect _effect;
+ Color _effect_color;
+ Time _fade_up_time;
+ Time _fade_down_time;
+};
+
+bool operator== (SubtitleString const & a, SubtitleString const & b);
+std::ostream& operator<< (std::ostream& s, SubtitleString const & sub);
+
+}
diff --git a/src/text.cc b/src/text.cc
new file mode 100644
index 00000000..5d2a2d1b
--- /dev/null
+++ b/src/text.cc
@@ -0,0 +1,41 @@
+/*
+ Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
+
+ This program 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.
+
+ This program 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 this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#include "text.h"
+#include "xml.h"
+#include "font.h"
+#include <libcxml/cxml.h>
+
+using std::string;
+using boost::shared_ptr;
+using boost::optional;
+using namespace dcp;
+
+Text::Text (shared_ptr<const cxml::Node> node)
+ : v_align (CENTER)
+{
+ text = node->content ();
+ v_position = node->number_attribute<float> ("VPosition");
+ optional<string> v = node->optional_string_attribute ("VAlign");
+ if (v) {
+ v_align = string_to_valign (v.get ());
+ }
+
+ font_nodes = type_children<Font> (node, "Font");
+}
diff --git a/src/text.h b/src/text.h
new file mode 100644
index 00000000..81992d6f
--- /dev/null
+++ b/src/text.h
@@ -0,0 +1,48 @@
+/*
+ Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
+
+ This program 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.
+
+ This program 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 this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#include "types.h"
+#include <boost/shared_ptr.hpp>
+#include <list>
+
+namespace cxml {
+ class Node;
+}
+
+namespace dcp {
+
+class Font;
+
+class Text
+{
+public:
+ Text ()
+ : v_position (0)
+ , v_align (TOP)
+ {}
+
+ Text (boost::shared_ptr<const cxml::Node> node);
+
+ float v_position;
+ VAlign v_align;
+ std::string text;
+ std::list<boost::shared_ptr<Font> > font_nodes;
+};
+
+}
diff --git a/src/types.h b/src/types.h
index 021d1ecf..85dc8362 100644
--- a/src/types.h
+++ b/src/types.h
@@ -105,14 +105,14 @@ struct EqualityOptions {
: max_mean_pixel_error (0)
, max_std_dev_pixel_error (0)
, max_audio_sample_error (0)
- , cpl_names_can_differ (false)
+ , cpl_annotation_texts_can_differ (false)
, mxf_names_can_differ (false)
{}
double max_mean_pixel_error;
double max_std_dev_pixel_error;
int max_audio_sample_error;
- bool cpl_names_can_differ;
+ bool cpl_annotation_texts_can_differ;
bool mxf_names_can_differ;
};
@@ -125,6 +125,11 @@ enum NoteType {
NOTE
};
+enum Standard {
+ INTEROP,
+ SMPTE
+};
+
/** @class Color
* @brief An RGB color (aka colour).
*/
diff --git a/src/util.cc b/src/util.cc
index 3807b4cc..fe89ca72 100644
--- a/src/util.cc
+++ b/src/util.cc
@@ -21,22 +21,6 @@
* @brief Utility methods.
*/
-#include <stdexcept>
-#include <sstream>
-#include <iostream>
-#include <iomanip>
-#include <boost/filesystem.hpp>
-#include <boost/lexical_cast.hpp>
-#include <openssl/sha.h>
-#include <libxml++/nodes/element.h>
-#include <libxml++/document.h>
-#include <xmlsec/xmldsig.h>
-#include <xmlsec/dl.h>
-#include <xmlsec/app.h>
-#include <xmlsec/crypto.h>
-#include "KM_util.h"
-#include "KM_fileio.h"
-#include "AS_DCP.h"
#include "util.h"
#include "exceptions.h"
#include "types.h"
@@ -44,6 +28,22 @@
#include "certificates.h"
#include "gamma_lut.h"
#include "xyz_frame.h"
+#include "KM_util.h"
+#include "KM_fileio.h"
+#include "AS_DCP.h"
+#include <xmlsec/xmldsig.h>
+#include <xmlsec/dl.h>
+#include <xmlsec/app.h>
+#include <xmlsec/crypto.h>
+#include <libxml++/nodes/element.h>
+#include <libxml++/document.h>
+#include <openssl/sha.h>
+#include <boost/filesystem.hpp>
+#include <boost/lexical_cast.hpp>
+#include <stdexcept>
+#include <sstream>
+#include <iostream>
+#include <iomanip>
using std::string;
using std::wstring;
@@ -79,10 +79,10 @@ dcp::make_uuid ()
* @return Digest.
*/
string
-dcp::make_digest (string filename, boost::function<void (float)>* progress)
+dcp::make_digest (boost::filesystem::path filename, boost::function<void (float)>* progress)
{
Kumu::FileReader reader;
- Kumu::Result_t r = reader.OpenRead (filename.c_str ());
+ Kumu::Result_t r = reader.OpenRead (filename.string().c_str ());
if (ASDCP_FAILURE (r)) {
boost::throw_exception (FileError ("could not open file to compute digest", filename, r));
}
diff --git a/src/util.h b/src/util.h
index f12f0ff0..5d7a9c4f 100644
--- a/src/util.h
+++ b/src/util.h
@@ -67,7 +67,7 @@ extern bool operator== (Size const & a, Size const & b);
extern bool operator!= (Size const & a, Size const & b);
extern std::string make_uuid ();
-extern std::string make_digest (std::string filename, boost::function<void (float)> *);
+extern std::string make_digest (boost::filesystem::path filename, boost::function<void (float)> *);
extern std::string content_kind_to_string (ContentKind kind);
extern ContentKind content_kind_from_string (std::string kind);
extern bool empty_or_white_space (std::string s);
@@ -75,7 +75,7 @@ extern boost::shared_ptr<XYZFrame> decompress_j2k (uint8_t* data, int64_t size,
extern void init ();
-extern void sign (xmlpp::Element* parent, CertificateChain const & certificates, boost::filesystem::path signer_key, bool interop);
+extern void sign (xmlpp::Element* parent, CertificateChain const & certificates, boost::filesystem::path signer_key, Standard standard);
extern void add_signature_value (xmlpp::Element* parent, CertificateChain const & certificates, boost::filesystem::path signer_key, std::string const & ns);
extern void add_signer (xmlpp::Element* parent, CertificateChain const & certificates, std::string const & ns);
diff --git a/src/wscript b/src/wscript
index 3e92900a..60d442fe 100644
--- a/src/wscript
+++ b/src/wscript
@@ -21,38 +21,48 @@ def build(bld):
dcp.cc
dcp_time.cc
exceptions.cc
+ file.cc
+ font.cc
gamma_lut.cc
image.cc
kdm.cc
key.cc
+ load_font.cc
metadata.cc
mono_picture_mxf.cc
mono_picture_mxf_writer.cc
mono_picture_frame.cc
mxf.cc
+ mxf_writer.cc
object.cc
picture_mxf.cc
picture_mxf_writer.cc
rec709_linearised_gamma_lut.cc
reel.cc
+ reel_asset.cc
+ reel_mono_picture_asset.cc
+ reel_picture_asset.cc
+ reel_sound_asset.cc
+ reel_stereo_picture_asset.cc
+ reel_subtitle_asset.cc
rgb_xyz.cc
signer.cc
signer_chain.cc
sound_mxf.cc
+ sound_mxf_writer.cc
sound_frame.cc
srgb_linearised_gamma_lut.cc
stereo_picture_mxf.cc
stereo_picture_mxf_writer.cc
stereo_picture_frame.cc
- subtitle_asset.cc
+ subtitle.cc
+ subtitle_content.cc
+ subtitle_string.cc
+ text.cc
types.cc
util.cc
version.cc
xyz_frame.cc
- parse/asset_map.cc
- parse/cpl.cc
- parse/pkl.cc
- parse/subtitle.cc
"""
headers = """