summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorCarl Hetherington <cth@carlh.net>2013-01-14 20:15:43 +0000
committerCarl Hetherington <cth@carlh.net>2013-01-14 20:15:43 +0000
commited6a471b61d36a3ba7e8696fa3e5606406c5cf62 (patch)
tree3ca098925eb269c4cd41ff22124773ba7d36c14b /src
parent67cf9c95d190b1f2a67d73c0a7f712e213b6e71a (diff)
parent62ee85a258aa9329544d8542dfbcc40ce8177a7a (diff)
Merge master
Diffstat (limited to 'src')
-rw-r--r--src/argb_frame.cc6
-rw-r--r--src/asset.cc2
-rw-r--r--src/asset_map.cc3
-rw-r--r--src/asset_map.h9
-rw-r--r--src/cpl_file.h16
-rw-r--r--src/dcp.cc11
-rw-r--r--src/dcp.h9
-rw-r--r--src/dcp_time.cc2
-rw-r--r--src/dcp_time.h8
-rw-r--r--src/exceptions.h1
-rw-r--r--src/mxf_asset.h1
-rw-r--r--src/reel.cc3
-rw-r--r--src/reel.h1
-rw-r--r--src/sound_asset.cc33
-rw-r--r--src/sound_asset.h5
-rw-r--r--src/types.cc15
-rw-r--r--src/types.h9
-rw-r--r--src/util.cc64
-rw-r--r--src/util.h17
-rw-r--r--src/version.h1
-rw-r--r--src/xml.h2
21 files changed, 157 insertions, 61 deletions
diff --git a/src/argb_frame.cc b/src/argb_frame.cc
index 7a9ad2b9..8e54e3b4 100644
--- a/src/argb_frame.cc
+++ b/src/argb_frame.cc
@@ -21,6 +21,11 @@
using namespace libdcp;
+/** Construct an empty ARGBFrame with a given width and height and with
+ * undefined contents.
+ * @param width Width in pixels.
+ * @param height Height in pixels.
+ */
ARGBFrame::ARGBFrame (int width, int height)
: _width (width)
, _height (height)
@@ -34,6 +39,7 @@ ARGBFrame::~ARGBFrame ()
delete[] _data;
}
+/** @return The stride, in bytes; that is, the number of bytes per row of the image */
int
ARGBFrame::stride () const
{
diff --git a/src/asset.cc b/src/asset.cc
index 62fdddf6..fa6947d1 100644
--- a/src/asset.cc
+++ b/src/asset.cc
@@ -86,7 +86,7 @@ string
Asset::digest () const
{
if (_digest.empty ()) {
- _digest = make_digest (path().string(), 0);
+ _digest = make_digest (path().string());
}
return _digest;
diff --git a/src/asset_map.cc b/src/asset_map.cc
index 4fda0a89..8fcc515f 100644
--- a/src/asset_map.cc
+++ b/src/asset_map.cc
@@ -21,6 +21,7 @@
* @brief Classes used to parse a AssetMap.
*/
+#include <boost/algorithm/string.hpp>
#include "asset_map.h"
#include "util.h"
@@ -55,7 +56,7 @@ Chunk::Chunk (xmlpp::Node const * node)
string const prefix = "file://";
- if (starts_with (path, prefix)) {
+ if (boost::algorithm::starts_with (path, prefix)) {
path = path.substr (prefix.length());
}
diff --git a/src/asset_map.h b/src/asset_map.h
index 10a0915f..8cf89b4b 100644
--- a/src/asset_map.h
+++ b/src/asset_map.h
@@ -27,6 +27,9 @@
namespace libdcp {
+/** @class Chunk
+ * @brief A simple parser for and representation of a \<Chunk\> node within an asset map.
+ */
class Chunk : public XMLNode
{
public:
@@ -39,6 +42,9 @@ public:
int64_t length;
};
+/** @class AssetMapAsset
+ * @brief A simple parser for and representation of an \<AssetMap\> node within an asset map.
+ */
class AssetMapAsset : public XMLNode
{
public:
@@ -50,6 +56,9 @@ public:
std::list<boost::shared_ptr<Chunk> > chunks;
};
+/** @class AssetMap
+ * @brief A simple parser for and representation of an asset map file.
+ */
class AssetMap : public XMLFile
{
public:
diff --git a/src/cpl_file.h b/src/cpl_file.h
index 14bcafd0..67b38a0d 100644
--- a/src/cpl_file.h
+++ b/src/cpl_file.h
@@ -27,6 +27,7 @@
namespace libdcp {
+/** @brief A simple parser for and representation of a CPL \<Picture\> node */
class Picture : public XMLNode
{
public:
@@ -44,7 +45,7 @@ public:
};
-/** CPL MainPicture node */
+/** @brief A simple parser for and representation of a CPL \<MainPicture\> node */
class MainPicture : public Picture
{
public:
@@ -52,7 +53,7 @@ public:
MainPicture (xmlpp::Node const * node);
};
-/** CPL MainStereoscopicPicture node */
+/** @brief A simple parser for and representation of a CPL \<MainStereoscopicPicture\> node */
class MainStereoscopicPicture : public Picture
{
public:
@@ -60,7 +61,7 @@ public:
MainStereoscopicPicture (xmlpp::Node const * node);
};
-/** CPL MainSound node */
+/** @brief A simple parser for and representation of a CPL \<MainSound\> node */
class MainSound : public XMLNode
{
public:
@@ -75,7 +76,7 @@ public:
int64_t duration;
};
-/** CPL MainSubtitle node */
+/** @brief A simple parser for and representation of a CPL \<MainSubtitle\> node */
class MainSubtitle : public XMLNode
{
public:
@@ -90,7 +91,7 @@ public:
int64_t duration;
};
-/** CPL AssetList node */
+/** @brief A simple parser for and representation of a CPL \<AssetList\> node */
class CPLAssetList : public XMLNode
{
public:
@@ -103,7 +104,7 @@ public:
boost::shared_ptr<MainSubtitle> main_subtitle;
};
-/** CPL Reel node */
+/** @brief A simple parser for and representation of a CPL \<Reel\> node */
class CPLReel : public XMLNode
{
public:
@@ -114,7 +115,8 @@ public:
boost::shared_ptr<CPLAssetList> asset_list;
};
-/** CPL ContentVersion node */
+
+/** @brief A simple parser for and representation of a CPL \<ContentVersion\> node */
class ContentVersion : public XMLNode
{
public:
diff --git a/src/dcp.cc b/src/dcp.cc
index 54ab6660..b3048bae 100644
--- a/src/dcp.cc
+++ b/src/dcp.cc
@@ -28,6 +28,7 @@
#include <iostream>
#include <boost/filesystem.hpp>
#include <boost/lexical_cast.hpp>
+#include <boost/algorithm/string.hpp>
#include <libxml++/libxml++.h>
#include <xmlsec/xmldsig.h>
#include <xmlsec/app.h>
@@ -208,7 +209,7 @@ DCP::read (bool require_mxfs)
boost::filesystem::path t = _directory;
t /= (*i)->chunks.front()->path;
- if (ends_with (t.string(), ".mxf") || ends_with (t.string(), ".ttf")) {
+ if (boost::algorithm::ends_with (t.string(), ".mxf") || boost::algorithm::ends_with (t.string(), ".ttf")) {
continue;
}
@@ -318,6 +319,12 @@ CPL::CPL (string directory, string name, ContentKind content_kind, int length, i
_uuid = make_uuid ();
}
+/** 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_map The corresponding asset map.
+ * @param require_mxfs true to throw an exception if a required MXF file does not exist.
+ */
CPL::CPL (string directory, string file, shared_ptr<const AssetMap> asset_map, bool require_mxfs)
: _directory (directory)
, _content_kind (FEATURE)
@@ -475,7 +482,7 @@ CPL::write_xml (shared_ptr<Encryption> crypt) const
doc.write_to_file_formatted (p.string(), "UTF-8");
- _digest = make_digest (p.string (), 0);
+ _digest = make_digest (p.string ());
_length = boost::filesystem::file_size (p.string ());
}
diff --git a/src/dcp.h b/src/dcp.h
index 63e579de..5a915019 100644
--- a/src/dcp.h
+++ b/src/dcp.h
@@ -60,6 +60,7 @@ public:
std::string signer_key;
};
+/** @brief A CPL within a DCP */
class CPL
{
public:
@@ -125,7 +126,9 @@ private:
/** reels */
std::list<boost::shared_ptr<const Reel> > _reels;
+ /** our UUID */
std::string _uuid;
+ /** a SHA1 digest of our XML */
mutable std::string _digest;
};
@@ -167,8 +170,12 @@ public:
*/
bool equals (DCP const & other, EqualityOptions options, std::list<std::string>& notes) 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<const CPL> > cpls () const {
return _cpls;
}
@@ -194,6 +201,7 @@ private:
*/
void write_assetmap (std::string pkl_uuid, int pkl_length) const;
+ /** @return Assets in all this CPLs in this DCP */
std::list<boost::shared_ptr<const Asset> > assets () const;
struct Files {
@@ -204,6 +212,7 @@ private:
/** the directory that we are writing to */
std::string _directory;
+ /** our CPLs */
std::list<boost::shared_ptr<const CPL> > _cpls;
};
diff --git a/src/dcp_time.cc b/src/dcp_time.cc
index c5a7affd..7c7c5298 100644
--- a/src/dcp_time.cc
+++ b/src/dcp_time.cc
@@ -222,6 +222,7 @@ libdcp::operator/ (Time a, Time const & b)
return float (at) / bt;
}
+/** @return A string of the form h:m:s:t */
string
Time::to_string () const
{
@@ -230,6 +231,7 @@ Time::to_string () const
return str.str ();
}
+/** @return This time in ticks */
int64_t
Time::to_ticks () const
{
diff --git a/src/dcp_time.h b/src/dcp_time.h
index eff69579..1b73e3e8 100644
--- a/src/dcp_time.h
+++ b/src/dcp_time.h
@@ -39,7 +39,13 @@ public:
* and a frames per second count.
*/
Time (int frame, int frames_per_second);
-
+
+ /** Construct a Time from hours, minutes, seconds and ticks.
+ * @param h_ Hours.
+ * @param m_ Minutes.
+ * @param s_ Seconds.
+ * @param t_ Ticks (where 1 tick is 4 milliseconds).
+ */
Time (int h_, int m_, int s_, int t_)
: h (h_)
, m (m_)
diff --git a/src/exceptions.h b/src/exceptions.h
index 25e51c9e..4c53a66d 100644
--- a/src/exceptions.h
+++ b/src/exceptions.h
@@ -55,6 +55,7 @@ private:
std::string _filename;
};
+/** @brief An exception related to an MXF file */
class MXFFileError : public FileError
{
public:
diff --git a/src/mxf_asset.h b/src/mxf_asset.h
index f68edc61..93fa9013 100644
--- a/src/mxf_asset.h
+++ b/src/mxf_asset.h
@@ -30,6 +30,7 @@ namespace ASDCP {
namespace libdcp
{
+/** @brief Parent class for assets which have MXF files */
class MXFAsset : public Asset
{
public:
diff --git a/src/reel.cc b/src/reel.cc
index d8703dd0..ae3080ad 100644
--- a/src/reel.cc
+++ b/src/reel.cc
@@ -45,6 +45,9 @@ Reel::write_to_cpl (xmlpp::Node* parent) const
if (_main_subtitle) {
_main_subtitle->write_to_cpl (asset_list);
}
+
+ s << " </AssetList>\n"
+ << " </Reel>\n";
}
bool
diff --git a/src/reel.h b/src/reel.h
index 52b3951a..0ad5ace2 100644
--- a/src/reel.h
+++ b/src/reel.h
@@ -31,6 +31,7 @@ class PictureAsset;
class SoundAsset;
class SubtitleAsset;
+/** @brief A reel within a DCP; the part which actually contains picture, sound and subtitle data */
class Reel
{
public:
diff --git a/src/sound_asset.cc b/src/sound_asset.cc
index 77267cbd..d964a46d 100644
--- a/src/sound_asset.cc
+++ b/src/sound_asset.cc
@@ -43,12 +43,22 @@ using boost::lexical_cast;
using namespace libdcp;
SoundAsset::SoundAsset (
- vector<string> const & files, string directory, string mxf_name, boost::signals2::signal<void (float)>* progress, int fps, int length, bool encrypted
+ vector<string> const & files,
+ string directory,
+ string mxf_name,
+ boost::signals2::signal<void (float)>* progress,
+ int fps,
+ int length,
+ int start_frame,
+ bool encrypted
)
: MXFAsset (directory, mxf_name, progress, fps, 0, length, encrypted)
, _channels (files.size ())
, _sampling_rate (0)
+ , _start_frame (start_frame)
{
+ assert (_channels);
+
construct (boost::bind (&SoundAsset::path_from_channel, this, _1, files));
}
@@ -57,18 +67,26 @@ SoundAsset::SoundAsset (
string directory,
string mxf_name,
boost::signals2::signal<void (float)>* progress,
- int fps, int length, int channels, bool encrypted
+ int fps,
+ int length,
+ int start_frame,
+ int channels,
+ bool encrypted
)
: MXFAsset (directory, mxf_name, progress, fps, 0, length, encrypted)
, _channels (channels)
, _sampling_rate (0)
+ , _start_frame (start_frame)
{
+ assert (_channels);
+
construct (get_path);
}
SoundAsset::SoundAsset (string directory, string mxf_name, int fps, int entry_point, int length)
: MXFAsset (directory, mxf_name, 0, fps, entry_point, length, false)
, _channels (0)
+ , _start_frame (0)
{
ASDCP::PCM::MXFReader reader;
if (ASDCP_FAILURE (reader.OpenRead (path().string().c_str()))) {
@@ -97,7 +115,7 @@ void
SoundAsset::construct (boost::function<string (Channel)> get_path)
{
ASDCP::Rational asdcp_fps (_fps, 1);
-
+
ASDCP::PCM::WAVParser pcm_parser_channel[_channels];
if (pcm_parser_channel[0].OpenRead (get_path(LEFT).c_str(), asdcp_fps)) {
throw FileError ("could not open WAV file for reading", get_path(LEFT));
@@ -154,6 +172,15 @@ SoundAsset::construct (boost::function<string (Channel)> get_path)
throw FileError ("could not open audio MXF for writing", path().string());
}
+ /* Skip through up to our _start_frame; this is pretty inefficient... */
+ for (int i = 0; i < _start_frame; ++i) {
+ for (int j = 0; j < _channels; ++j) {
+ if (ASDCP_FAILURE (pcm_parser_channel[j].ReadFrame (frame_buffer_channel[j]))) {
+ throw MiscError ("could not read audio frame");
+ }
+ }
+ }
+
for (int i = 0; i < _length; ++i) {
for (int j = 0; j < _channels; ++j) {
diff --git a/src/sound_asset.h b/src/sound_asset.h
index 67115606..2b925641 100644
--- a/src/sound_asset.h
+++ b/src/sound_asset.h
@@ -44,6 +44,7 @@ public:
* @param progress Signal to inform of progress.
* @param fps Frames per second.
* @param length Length in frames.
+ * @param start_frame Frame in the source to start writing from.
* @param encrypted true if asset should be encrypted.
*/
SoundAsset (
@@ -53,6 +54,7 @@ public:
boost::signals2::signal<void (float)>* progress,
int fps,
int length,
+ int start_frame
bool encrypted
);
@@ -64,6 +66,7 @@ public:
* @param progress Signal to inform of progress.
* @param fps Frames per second.
* @param length Length in frames.
+ * @param start_frame Frame in the source to start writing from.
* @param channels Number of audio channels.
* @param encrypted true if asset should be encrypted.
*/
@@ -74,6 +77,7 @@ public:
boost::signals2::signal<void (float)>* progress,
int fps,
int length,
+ int start_frame,
int channels,
bool encrypted
);
@@ -112,6 +116,7 @@ private:
/** Number of channels in the asset */
int _channels;
int _sampling_rate;
+ int _start_frame;
};
}
diff --git a/src/types.cc b/src/types.cc
index a00e8261..ac01ae45 100644
--- a/src/types.cc
+++ b/src/types.cc
@@ -49,6 +49,10 @@ Color::Color (int r_, int g_, int b_)
}
+/** Construct a Color from an ARGB hex string; the alpha value is ignored.
+ * @param argb_hex A string of the form AARRGGBB, where e.g. RR is a two-character
+ * hex value.
+ */
Color::Color (string argb_hex)
{
int alpha;
@@ -57,6 +61,9 @@ Color::Color (string argb_hex)
}
}
+/** @return An ARGB string of the form AARRGGBB, where e.g. RR is a two-character
+ * hex value. The alpha value will always be FF (ie 255; maximum alpha).
+ */
string
Color::to_argb_string () const
{
@@ -72,12 +79,20 @@ Color::to_argb_string () const
return t;
}
+/** operator== for Colors.
+ * @param a First color to compare.
+ * @param b Second color to compare.
+ */
bool
libdcp::operator== (Color const & a, Color const & b)
{
return (a.r == b.r && a.g == b.g && a.b == b.b);
}
+/** operator!= for Colors.
+ * @param a First color to compare.
+ * @param b Second color to compare.
+ */
bool
libdcp::operator!= (Color const & a, Color const & b)
{
diff --git a/src/types.h b/src/types.h
index 433a910c..f1b5f640 100644
--- a/src/types.h
+++ b/src/types.h
@@ -105,6 +105,9 @@ struct EqualityOptions {
int max_audio_sample_error;
};
+/** @class Color
+ * @brief An RGB color (aka colour).
+ */
class Color
{
public:
@@ -112,9 +115,9 @@ public:
Color (int r_, int g_, int b_);
Color (std::string argb_hex);
- int r;
- int g;
- int b;
+ int r; ///< red component, from 0 to 255
+ int g; ///< green component, from 0 to 255
+ int b; ///< blue component, from 0 to 255
std::string to_argb_string () const;
};
diff --git a/src/util.cc b/src/util.cc
index f2ee35e3..8277b2bf 100644
--- a/src/util.cc
+++ b/src/util.cc
@@ -51,6 +51,9 @@ using std::list;
using boost::shared_ptr;
using namespace libdcp;
+/** Create a UUID.
+ * @return UUID.
+ */
string
libdcp::make_uuid ()
{
@@ -61,11 +64,14 @@ libdcp::make_uuid ()
return string (buffer);
}
+
+/** Create a digest for a file.
+ * @param filename File name.
+ * @return Digest.
+ */
string
-libdcp::make_digest (string filename, boost::signals2::signal<void (float)>* progress)
+libdcp::make_digest (string filename)
{
- int const file_size = boost::filesystem::file_size (filename);
-
Kumu::FileReader reader;
if (ASDCP_FAILURE (reader.OpenRead (filename.c_str ()))) {
throw FileError ("could not open file to compute digest", filename);
@@ -88,10 +94,6 @@ libdcp::make_digest (string filename, boost::signals2::signal<void (float)>* pro
SHA1_Update (&sha, read_buffer.Data(), read);
done += read;
-
- if (progress) {
- (*progress) (0.5 + (0.5 * done / file_size));
- }
}
byte_t byte_buffer[20];
@@ -101,6 +103,11 @@ libdcp::make_digest (string filename, boost::signals2::signal<void (float)>* pro
return Kumu::base64encode (byte_buffer, 20, digest, 64);
}
+/** Convert a content kind to a string which can be used in a
+ * <ContentKind> node.
+ * @param kind ContentKind.
+ * @return string.
+ */
string
libdcp::content_kind_to_string (ContentKind kind)
{
@@ -130,9 +137,16 @@ libdcp::content_kind_to_string (ContentKind kind)
assert (false);
}
+/** Convert a string from a <ContentKind> node to a libdcp ContentKind.
+ * Reasonably tolerant about varying case.
+ * @param type Content kind string.
+ * @return libdcp ContentKind.
+ */
libdcp::ContentKind
libdcp::content_kind_from_string (string type)
{
+ /* XXX: should probably just convert type to lower-case and have done with it */
+
if (type == "feature") {
return FEATURE;
} else if (type == "short") {
@@ -157,27 +171,16 @@ libdcp::content_kind_from_string (string type)
assert (false);
}
-
-bool
-libdcp::starts_with (string big, string little)
-{
- if (little.size() > big.size()) {
- return false;
- }
-
- return big.substr (0, little.length()) == little;
-}
-
-bool
-libdcp::ends_with (string big, string little)
-{
- if (little.size() > big.size()) {
- return false;
- }
-
- return big.compare (big.length() - little.length(), little.length(), little) == 0;
-}
+/** Decompress a JPEG2000 image to a bitmap.
+ * @param data JPEG2000 data.
+ * @param size Size of data in bytes.
+ * @param reduce A power of 2 by which to reduce the size of the decoded image;
+ * e.g. 0 reduces by (2^0 == 1), ie keeping the same size.
+ * 1 reduces by (2^1 == 2), ie halving the size of the image.
+ * This is useful for scaling 4K DCP images down to 2K.
+ * @return openjpeg image, which the caller must call opj_image_destroy() on.
+ */
opj_image_t *
libdcp::decompress_j2k (uint8_t* data, int64_t size, int reduce)
{
@@ -201,6 +204,10 @@ libdcp::decompress_j2k (uint8_t* data, int64_t size, int reduce)
return image;
}
+/** Convert an openjpeg XYZ image to RGB.
+ * @param xyz_frame Frame in XYZ.
+ * @return RGB image.
+ */
shared_ptr<ARGBFrame>
libdcp::xyz_to_rgb (opj_image_t* xyz_frame)
{
@@ -263,6 +270,9 @@ libdcp::xyz_to_rgb (opj_image_t* xyz_frame)
return argb_frame;
}
+/** @param s A string.
+ * @return true if the string contains only space, newline or tab characters, or is empty.
+ */
bool
libdcp::empty_or_white_space (string s)
{
diff --git a/src/util.h b/src/util.h
index 3b60e0c7..ddc5a322 100644
--- a/src/util.h
+++ b/src/util.h
@@ -23,7 +23,6 @@
#include <string>
#include <stdint.h>
-#include <boost/signals2.hpp>
#include <openjpeg.h>
#include "types.h"
@@ -36,25 +35,11 @@ namespace libdcp {
class ARGBFrame;
class CertificateChain;
-/** Create a UUID.
- * @return UUID.
- */
extern std::string make_uuid ();
-
-/** Create a digest for a file.
- * @param filename File name.
- * @param progress If non-0, a signal which will be emitted periodically to update
- * progress; the parameter will start at 0.5 and proceed to 1.
- * @return Digest.
- */
-extern std::string make_digest (std::string filename, boost::signals2::signal<void (float)>* progress);
-
+extern std::string make_digest (std::string filename);
extern std::string content_kind_to_string (ContentKind kind);
extern ContentKind content_kind_from_string (std::string kind);
-extern bool starts_with (std::string big, std::string little);
-extern bool ends_with (std::string big, std::string little);
extern bool empty_or_white_space (std::string s);
-
extern opj_image_t* decompress_j2k (uint8_t* data, int64_t size, int reduce);
extern boost::shared_ptr<ARGBFrame> xyz_to_rgb (opj_image_t* xyz_frame);
diff --git a/src/version.h b/src/version.h
index 7fd9dc25..52abd13a 100644
--- a/src/version.h
+++ b/src/version.h
@@ -3,5 +3,6 @@ namespace libdcp {
extern char const * version;
extern char const * git_commit;
+extern bool built_with_debug;
}
diff --git a/src/xml.h b/src/xml.h
index acace846..6fc0d0fa 100644
--- a/src/xml.h
+++ b/src/xml.h
@@ -18,6 +18,7 @@ namespace xmlpp {
namespace libdcp {
+/** @brief A helper class for XML nodes */
class XMLNode
{
public:
@@ -86,6 +87,7 @@ private:
std::list<Glib::ustring> _taken;
};
+/** @brief A helper class for XML files */
class XMLFile : public XMLNode
{
public: