*/
+/** @file src/array_data.cc
+ * @brief ArrayData class
+ */
+
+
#include "array_data.h"
#include "util.h"
#include "exceptions.h"
ArrayData::ArrayData ()
- : _size (0)
{
}
private:
boost::shared_array<uint8_t> _data;
/** amount of `valid' data in _data; the array may be larger */
- int _size;
+ int _size = 0;
};
*/
+/** @file src/asset_reader.h
+ * @brief AssetReader class
+ */
+
+
#ifndef LIBDCP_ASSET_READER_H
#define LIBDCP_ASSET_READER_H
namespace dcp {
+class AtmosAsset;
+class MonoPictureAsset;
+class SoundAsset;
+class StereoPictureAsset;
+
+
template <class R, class F>
class AssetReader
{
public:
- explicit AssetReader (Asset const * asset, boost::optional<Key> key, Standard standard)
- : _crypto_context (new DecryptionContext(key, standard))
- {
- _reader = new R ();
- DCP_ASSERT (asset->file());
- auto const r = _reader->OpenRead (asset->file()->string().c_str());
- if (ASDCP_FAILURE(r)) {
- delete _reader;
- boost::throw_exception (FileError("could not open MXF file for reading", asset->file().get(), r));
- }
- }
-
AssetReader (AssetReader const&) = delete;
AssetReader& operator== (AssetReader const&) = delete;
std::shared_ptr<const F> get_frame (int n) const
{
+ /* Can't use make_shared here as the constructor is private */
return std::shared_ptr<const F> (new F(_reader, n, _crypto_context));
}
protected:
R* _reader = nullptr;
std::shared_ptr<DecryptionContext> _crypto_context;
+
+private:
+ friend class AtmosAsset;
+ friend class MonoPictureAsset;
+ friend class SoundAsset;
+ friend class StereoPictureAsset;
+
+ explicit AssetReader (Asset const * asset, boost::optional<Key> key, Standard standard)
+ : _crypto_context (new DecryptionContext(key, standard))
+ {
+ _reader = new R ();
+ DCP_ASSERT (asset->file());
+ auto const r = _reader->OpenRead (asset->file()->string().c_str());
+ if (ASDCP_FAILURE(r)) {
+ delete _reader;
+ boost::throw_exception (FileError("could not open MXF file for reading", asset->file().get(), r));
+ }
+ }
};
/** @file src/asset_writer.h
- * @brief AssetWriter class.
+ * @brief AssetWriter class
*/
}
-/** @return true if anything was written by this writer */
bool
AssetWriter::finalize ()
{
/** @file src/asset_writer.h
- * @brief AssetWriter class.
+ * @brief AssetWriter class
*/
AssetWriter& operator= (AssetWriter const&) = delete;
virtual ~AssetWriter () {}
+
+ /** @return true if anything was written by this writer */
virtual bool finalize ();
int64_t frames_written () const {
*/
+/** @file src/atmos_asset.cc
+ * @brief AtmosAsset class
+ */
+
+
#include "atmos_asset.h"
#include "atmos_asset_reader.h"
#include "atmos_asset_writer.h"
AtmosAsset::AtmosAsset (Fraction edit_rate, int first_frame, int max_channel_count, int max_object_count, int atmos_version)
: MXF (Standard::SMPTE)
, _edit_rate (edit_rate)
- , _intrinsic_duration (0)
, _first_frame (first_frame)
, _max_channel_count (max_channel_count)
, _max_object_count (max_object_count)
shared_ptr<AtmosAssetReader>
AtmosAsset::start_read () const
{
- return make_shared<AtmosAssetReader>(this, key(), Standard::SMPTE);
+ /* Can't use make_shared here since the constructor is protected */
+ return shared_ptr<AtmosAssetReader>(new AtmosAssetReader(this, key(), Standard::SMPTE));
}
friend class AtmosAssetWriter;
Fraction _edit_rate;
- int64_t _intrinsic_duration;
- int _first_frame;
- int _max_channel_count;
- int _max_object_count;
+ int64_t _intrinsic_duration = 0;
+ int _first_frame = 0;
+ int _max_channel_count = 0;
+ int _max_object_count = 0;
std::string _atmos_id;
- int _atmos_version;
+ int _atmos_version = 0;
};
/*
- Copyright (C) 2016 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2016-2021 Carl Hetherington <cth@carlh.net>
This file is part of libdcp.
files in the program, then also delete it here.
*/
+
+/** @file src/atmos_asset_reader.h
+ * @brief AtmosAssetReader typedef
+ */
+
+
#include "asset_reader.h"
#include "atmos_frame.h"
+
namespace dcp {
+
typedef AssetReader<ASDCP::ATMOS::MXFReader, AtmosFrame> AtmosAssetReader;
+
}
*/
+/** @file src/atmos_asset_writer.cc
+ * @brief AtmosAssetWriter class
+ */
+
+
#include "atmos_asset_writer.h"
#include "atmos_asset.h"
#include "exceptions.h"
++_frames_written;
}
+
bool
AtmosAssetWriter::finalize ()
{
/*
- Copyright (C) 2016 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2016-2021 Carl Hetherington <cth@carlh.net>
This file is part of libdcp.
files in the program, then also delete it here.
*/
+
/** @file src/atmos_frame.h
- * @brief AtmosFrame class.
+ * @brief AtmosFrame typedef
*/
+
#ifndef LIBDCP_ATMOS_FRAME_H
#define LIBDCP_ATMOS_FRAME_H
+
#include "frame.h"
+
namespace dcp {
+
typedef Frame<ASDCP::ATMOS::MXFReader, ASDCP::DCData::FrameBuffer> AtmosFrame;
+
}
+
#endif
/*
- Copyright (C) 2020 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2020-2021 Carl Hetherington <cth@carlh.net>
This file is part of libdcp.
*/
+/** @file src/bitstream.cc
+ * @brief Bitstream class
+ */
+
+
#include "bitstream.h"
#include "dcp_assert.h"
#include <iostream>
/*
- Copyright (C) 2020 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2020-2021 Carl Hetherington <cth@carlh.net>
This file is part of libdcp.
*/
+/** @file src/bitstream.h
+ * @brief Bitstream class
+ */
+
+
#include <boost/crc.hpp>
#include <boost/optional.hpp>
#include <stdint.h>
namespace dcp {
+
class Bitstream
{
public:
boost::optional<boost::crc_basic<16> > _crc;
};
+
}
/** @file src/certificate.cc
- * @brief Certificate class.
+ * @brief Certificate class
*/
/** @file src/certificate.h
- * @brief Certificate class.
+ * @brief Certificate class
*/
}
+
#endif
/*
- Copyright (C) 2016 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2016-2021 Carl Hetherington <cth@carlh.net>
This file is part of libdcp.
files in the program, then also delete it here.
*/
+
+/** file src/chromaticity.cc
+ * brief Chromaticity class
+ */
+
+
#include "chromaticity.h"
+
using namespace dcp;
+
Chromaticity
Chromaticity::D65 ()
{
/*
- Copyright (C) 2015 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2015-2021 Carl Hetherington <cth@carlh.net>
This file is part of libdcp.
files in the program, then also delete it here.
*/
+
/** @file src/chromaticity.h
- * @brief Chromaticity class.
+ * @brief Chromaticity class
*/
+
#ifndef DCP_CHROMATICITY_H
#define DCP_CHROMATICITY_H
+
#include <cmath>
+
namespace dcp {
+
/** @class Chromaticity
* @brief A representation of a x,y,z chromaticity, where z = 1 - x - y
*/
class Chromaticity
{
public:
- Chromaticity ()
- : x (0)
- , y (0)
- {}
+ Chromaticity () {}
Chromaticity (double x_, double y_)
: x (x_)
, y (y_)
{}
- double x;
- double y;
+ double x = 0;
+ double y = 0;
double z () const {
return 1 - x - y;
/** @return true if this Chromaticity's x and y are within epsilon of other */
bool about_equal (Chromaticity const & other, float epsilon) const {
- return std::fabs (x - other.x) < epsilon && std::fabs (y - other.y) < epsilon;
+ return std::fabs(x - other.x) < epsilon && std::fabs(y - other.y) < epsilon;
}
static Chromaticity D65 ();
};
+
}
+
#endif
files in the program, then also delete it here.
*/
+
+/** @file src/colour_conversion.cc
+ * @brief ColourConversion class
+ */
+
+
#include "colour_conversion.h"
#include "gamma_transfer_function.h"
#include "modified_gamma_transfer_function.h"
#include <boost/numeric/ublas/lu.hpp>
#include <boost/numeric/ublas/io.hpp>
+
using std::shared_ptr;
using std::make_shared;
using boost::optional;
using namespace dcp;
+
ColourConversion const &
ColourConversion::srgb_to_xyz ()
{
- static ColourConversion* c = new ColourConversion (
+ static auto c = new ColourConversion (
make_shared<ModifiedGammaTransferFunction>(2.4, 0.04045, 0.055, 12.92),
YUVToRGB::REC601,
Chromaticity (0.64, 0.33),
ColourConversion const &
ColourConversion::rec601_to_xyz ()
{
- static ColourConversion* c = new ColourConversion (
+ static auto c = new ColourConversion (
make_shared<GammaTransferFunction>(2.2),
YUVToRGB::REC601,
Chromaticity (0.64, 0.33),
ColourConversion const &
ColourConversion::rec709_to_xyz ()
{
- static ColourConversion* c = new ColourConversion (
+ static auto c = new ColourConversion (
make_shared<GammaTransferFunction>(2.2),
YUVToRGB::REC709,
Chromaticity (0.64, 0.33),
ColourConversion const &
ColourConversion::p3_to_xyz ()
{
- static ColourConversion* c = new ColourConversion (
+ static auto c = new ColourConversion (
make_shared<GammaTransferFunction>(2.6),
YUVToRGB::REC709,
Chromaticity (0.68, 0.32),
/* According to Olivier on DCP-o-matic bug #832, Rec. 1886 is Rec. 709 with
2.4 gamma, so here goes ...
*/
- static ColourConversion* c = new ColourConversion (
+ static auto c = new ColourConversion (
make_shared<GammaTransferFunction>(2.4),
YUVToRGB::REC709,
Chromaticity (0.64, 0.33),
ColourConversion const &
ColourConversion::rec2020_to_xyz ()
{
- static ColourConversion* c = new ColourConversion (
+ static auto c = new ColourConversion (
make_shared<GammaTransferFunction>(2.4),
YUVToRGB::REC709,
Chromaticity (0.708, 0.292),
ColourConversion const &
ColourConversion::s_gamut3_to_xyz ()
{
- static ColourConversion* c = new ColourConversion (
+ static auto c = new ColourConversion (
make_shared<SGamut3TransferFunction>(),
YUVToRGB::REC709,
Chromaticity (0.73, 0.280),
}
+
bool
ColourConversion::about_equal (ColourConversion const & other, float epsilon) const
{
return false;
}
+
boost::numeric::ublas::matrix<double>
ColourConversion::rgb_to_xyz () const
{
return C;
}
+
boost::numeric::ublas::matrix<double>
ColourConversion::xyz_to_rgb () const
{
- boost::numeric::ublas::matrix<double> A (rgb_to_xyz ());
+ boost::numeric::ublas::matrix<double> A (rgb_to_xyz());
/* permutation matrix for the LU-factorization */
- boost::numeric::ublas::permutation_matrix<std::size_t> pm (A.size1 ());
+ boost::numeric::ublas::permutation_matrix<std::size_t> pm (A.size1());
/* perform LU-factorization */
int const r = lu_factorize (A, pm);
/* create identity matrix of inverse */
boost::numeric::ublas::matrix<double> xyz_to_rgb (3, 3);
- xyz_to_rgb.assign (boost::numeric::ublas::identity_matrix<double> (A.size1 ()));
+ xyz_to_rgb.assign (boost::numeric::ublas::identity_matrix<double> (A.size1()));
/* backsubstitute to get the inverse */
lu_substitute (A, pm, xyz_to_rgb);
return xyz_to_rgb;
}
+
boost::numeric::ublas::matrix<double>
ColourConversion::bradford () const
{
/*
- Copyright (C) 2014-2015 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2014-2021 Carl Hetherington <cth@carlh.net>
This file is part of libdcp.
files in the program, then also delete it here.
*/
+
/** @file src/colour_conversion.h
* @brief ColourConversion class.
*/
+
#ifndef DCP_COLOUR_CONVERSION_H
#define DCP_COLOUR_CONVERSION_H
+
#include "chromaticity.h"
#include <memory>
#if BOOST_VERSION >= 106400
#include <boost/numeric/ublas/matrix.hpp>
#include <boost/optional.hpp>
+
namespace dcp {
+
class TransferFunction;
+
enum class YUVToRGB {
REC601,
REC709,
COUNT
};
+
/** @class ColourConversion
* @brief A representation of all the parameters involved the colourspace conversion
- * of a YUV image to XYZ (via RGB).
+ * of a YUV image to XYZ (via RGB)
*/
class ColourConversion
{
std::shared_ptr<const TransferFunction> _out;
};
+
}
+
#endif
*/
+/** @file src/combine.cc
+ * @brief Method to combine DCPs
+ */
+
+
#include "asset.h"
#include "combine.h"
#include "cpl.h"
continue;
}
- optional<path> file = j->file();
+ auto file = j->file();
DCP_ASSERT (file);
path new_path = make_unique(output / file->filename());
- shared_ptr<dcp::InteropSubtitleAsset> sub = dynamic_pointer_cast<dcp::InteropSubtitleAsset>(j);
+ auto sub = dynamic_pointer_cast<dcp::InteropSubtitleAsset>(j);
if (sub) {
/* Interop fonts are really fiddly. The font files are assets (in the ASSETMAP)
* and also linked from the font XML by filename. We have to fix both these things,
* and re-write the font XML file since the font URI might have changed if it's a duplicate
* with another DCP.
*/
- map<string, path> fonts = sub->font_filenames ();
- for (map<string, path>::const_iterator k = fonts.begin(); k != fonts.end(); ++k) {
- sub->set_font_file (k->first, make_unique(output / k->second.filename()));
+ auto fonts = sub->font_filenames ();
+ for (auto const& k: fonts) {
+ sub->set_font_file (k.first, make_unique(output / k.second.filename()));
}
sub->write (new_path);
} else if (!dynamic_pointer_cast<dcp::FontAsset>(j)) {
/* Take care of everything else that's not a Interop subtitle asset, Interop font file
* or CPL.
*/
- optional<path> file = j->file();
+ auto file = j->file();
DCP_ASSERT (file);
path new_path = make_unique(output / file->filename());
create_hard_link_or_copy (*file, new_path);
*/
+/** @file src/combine.h
+ * @brief Method to combine DCPs
+ */
+
+
#include "compose.hpp"
#include "version.h"
#include <boost/filesystem.hpp>
namespace dcp {
+
class CertificateChain;
+
void combine (
std::vector<boost::filesystem::path> inputs,
boost::filesystem::path output,
std::shared_ptr<const CertificateChain> signer = std::shared_ptr<CertificateChain>()
);
+
}
files in the program, then also delete it here.
*/
+
+/** @file src/cpl.cc
+ * @brief CPL class
+ */
+
+
#include "cpl.h"
#include "util.h"
#include "reel.h"
#include <libxml++/libxml++.h>
#include <boost/algorithm/string.hpp>
+
using std::string;
using std::list;
using std::pair;
_content_versions.push_back (cv);
}
-/** Construct a CPL object from a XML file */
+
CPL::CPL (boost::filesystem::path file)
: Asset (file)
, _content_kind (ContentKind::FEATURE)
}
}
-
f.ignore_child ("Issuer");
f.ignore_child ("Signer");
f.ignore_child ("Signature");
f.done ();
}
-/** Add a reel to this CPL.
- * @param reel Reel to add.
- */
+
void
CPL::add (std::shared_ptr<Reel> reel)
{
_reels.push_back (reel);
}
-/** Write an CompositonPlaylist XML file.
- *
- * @param file Filename to write.
- * @param standard INTEROP or SMPTE.
- * @param signer Signer to sign the CPL, or 0 to add no signature.
- */
+
void
CPL::write_xml (boost::filesystem::path file, Standard standard, shared_ptr<const CertificateChain> signer) const
{
return c;
}
+
bool
CPL::equals (shared_ptr<const Asset> other, EqualityOptions opt, NoteHandler note) const
{
return true;
}
-/** @return true if we have any encrypted content */
+
bool
CPL::any_encrypted () const
{
}
-/** @return true if we have all our encryptable content is encrypted */
bool
CPL::all_encrypted () const
{
}
-/** Add a KDM to this CPL. If the KDM is for any of this CPLs assets it will be used
- * to decrypt those assets.
- * @param kdm KDM.
- */
void
CPL::add (DecryptedKDM const & kdm)
{
/** @class CPL
- * @brief A Composition Playlist.
+ * @brief A Composition Playlist
*/
class CPL : public Asset
{
public:
CPL (std::string annotation_text, ContentKind content_kind);
+
+ /** Construct a CPL object from a XML file */
explicit CPL (boost::filesystem::path file);
bool equals (
NoteHandler note
) const;
+ /** Add a reel to this CPL
+ * @param reel Reel to add
+ */
void add (std::shared_ptr<Reel> reel);
+
+ /** Add a KDM to this CPL. If the KDM is for any of this CPLs assets it will be used
+ * to decrypt those assets.
+ * @param kdm KDM.
+ */
void add (DecryptedKDM const &);
/** @return the reels in this CPL */
std::vector<std::shared_ptr<const ReelMXF>> reel_mxfs () const;
std::vector<std::shared_ptr<ReelMXF>> reel_mxfs ();
+ /** @return true if we have any encrypted content */
bool any_encrypted () const;
+
+ /** @return true if we have all our encryptable content is encrypted */
bool all_encrypted () const;
+ /** Write an CompositonPlaylist XML file
+ *
+ * @param file Filename to write
+ * @param standard INTEROP or SMPTE
+ * @param signer Signer to sign the CPL, or 0 to add no signature
+ */
void write_xml (
boost::filesystem::path file,
Standard standard,
/*
- Copyright (C) 2012-2018 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2021 Carl Hetherington <cth@carlh.net>
This file is part of libdcp.
files in the program, then also delete it here.
*/
+
+/** @file src/crypto_context.h
+ * @class CryptoContext class
+ */
+
+
#ifndef LIBDCP_CRYPTO_CONTEXT_H
#define LIBDCP_CRYPTO_CONTEXT_H
+
#include "key.h"
#include "types.h"
#include "exceptions.h"
#include <asdcp/KM_prng.h>
#include <boost/optional.hpp>
+
namespace dcp {
+
template <class T>
class CryptoContext
{
public:
CryptoContext (boost::optional<Key> key, Standard standard)
- : _context (0)
- , _hmac (0)
+ : _context (nullptr)
+ , _hmac (nullptr)
{
if (!key) {
return;
}
- _context = new T;
- if (ASDCP_FAILURE (_context->InitKey (key->value ()))) {
+ _context = new T ();
+ if (ASDCP_FAILURE (_context->InitKey(key->value()))) {
throw MiscError ("could not set up crypto context");
}
type = ASDCP::LS_MXF_SMPTE;
}
- if (ASDCP_FAILURE (_hmac->InitKey (key->value(), type))) {
+ if (ASDCP_FAILURE (_hmac->InitKey(key->value(), type))) {
throw MiscError ("could not set up HMAC context");
}
}
ASDCP::HMACContext* _hmac;
};
+
typedef CryptoContext<ASDCP::AESEncContext> EncryptionContext;
typedef CryptoContext<ASDCP::AESDecContext> DecryptionContext;
+
}
+
#endif
/*
- Copyright (C) 2015-2020 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2015-2021 Carl Hetherington <cth@carlh.net>
This file is part of libdcp.
*/
+/** @file src/data.cc
+ * @brief Data class
+ */
+
+
#include "data.h"
-#include "util.h"
#include "exceptions.h"
+#include "util.h"
#include <cstdio>
#include <cerrno>
void
Data::write (boost::filesystem::path file) const
{
- FILE* f = fopen_boost (file, "wb");
+ auto f = fopen_boost (file, "wb");
if (!f) {
throw FileError ("could not write to file", file, errno);
}
size_t const r = fwrite (data(), 1, size(), f);
+ fclose (f);
if (r != size_t(size())) {
- fclose (f);
throw FileError ("could not write to file", file, errno);
}
- fclose (f);
}
*/
+/** @file src/data.h
+ * @brief Data class
+ */
+
+
#ifndef LIBDCP_DATA_H
#define LIBDCP_DATA_H
}
+
#endif
files in the program, then also delete it here.
*/
+
/** @file src/dcp.cc
- * @brief DCP class.
+ * @brief DCP class
*/
+
#include "raw_convert.h"
#include "dcp.h"
#include "sound_asset.h"
void
-DCP::add (std::shared_ptr<CPL> cpl)
+DCP::add (shared_ptr<CPL> cpl)
{
_cpls.push_back (cpl);
}
/** @file src/dcp.h
- * @brief DCP class.
+ * @brief DCP class
*/
/*
- Copyright (C) 2014 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2014-2021 Carl Hetherington <cth@carlh.net>
This file is part of libdcp.
files in the program, then also delete it here.
*/
+
+/** @file src/dcp_assert.h
+ * @brief DCP_ASSERT macro
+ */
+
+
#include "exceptions.h"
+
#define DCP_ASSERT(x) if (!(x)) throw dcp::ProgrammingError (__FILE__, __LINE__);
/*
- Copyright (C) 2012-2016 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2021 Carl Hetherington <cth@carlh.net>
This file is part of libdcp.
files in the program, then also delete it here.
*/
+
/** @file src/dcp_time.cc
- * @brief Time class.
+ * @brief Time class
*/
+
#include "raw_convert.h"
#include "dcp_time.h"
#include "exceptions.h"
#include <vector>
#include <cmath>
+
using namespace std;
using namespace boost;
using namespace dcp;
+
Time::Time (int frame, double frames_per_second, int tcr_)
{
set (double (frame) / frames_per_second, tcr_);
}
-/** Construct a Time from a number of seconds and a timecode rate.
- *
- * @param seconds A number of seconds.
- * @param tcr_ Timecode rate.
- */
+
Time::Time (double seconds, int tcr_)
{
set (seconds, tcr_);
}
+
/** Construct a Time with specified timecode rate and using the supplied
* number of seconds.
*
}
}
-/** @param time String of the form
- * HH:MM:SS:EE for SMPTE
- * HH:MM:SS:E[E[E]] or HH:MM:SS.s[s[s]] for Interop
- * where HH are hours, MM minutes, SS seconds, EE editable units and
- * sss millseconds.
- *
- * @param tcr_ Timecode rate if this is a SMPTE time, otherwise empty for an Interop time.
- */
+
Time::Time (string time, optional<int> tcr_)
{
vector<string> b;
}
}
+
bool
dcp::operator== (Time const & a, Time const & b)
{
return (a.h == b.h && a.m == b.m && a.s == b.s && (a.e * b.tcr) == (b.e * a.tcr));
}
+
bool
dcp::operator!= (Time const & a, Time const & b)
{
return !(a == b);
}
+
bool
dcp::operator<= (Time const & a, Time const & b)
{
return a < b || a == b;
}
+
bool
dcp::operator>= (Time const & a, Time const & b)
{
return a > b || a == b;
}
+
bool
dcp::operator< (Time const & a, Time const & b)
{
return (a.e * b.tcr) < (b.e * a.tcr);
}
+
bool
dcp::operator> (Time const & a, Time const & b)
{
return (a.e * b.tcr) > (b.e * a.tcr);
}
+
ostream &
dcp::operator<< (ostream& s, Time const & t)
{
return s;
}
+
dcp::Time
dcp::operator+ (Time a, Time b)
{
return r;
}
+
dcp::Time
dcp::operator- (Time a, Time b)
{
return r;
}
+
float
dcp::operator/ (Time a, Time const & b)
{
return float (at) / bt;
}
-/** @return A string of the form h:m:s:e padded as in 00:00:00:000 (for Interop) or 00:00:00:00 (for SMPTE) */
+
string
Time::as_string (Standard standard) const
{
return buffer;
}
-/** @param tcr_ Timecode rate with which the return value should be counted.
- * @return the total number of editable units that this time consists of at the specified timecode rate, rounded up
- * to the nearest editable unit. For example, as_editable_units (24) returns the total time in frames at 24fps.
- */
+
int64_t
Time::as_editable_units (int tcr_) const
{
- return ceil (int64_t(e) * double (tcr_) / tcr) + int64_t(s) * tcr_ + int64_t(m) * 60 * tcr_ + int64_t(h) * 60 * 60 * tcr_;
+ return ceil(int64_t(e) * double(tcr_) / tcr) + int64_t(s) * tcr_ + int64_t(m) * 60 * tcr_ + int64_t(h) * 60 * 60 * tcr_;
}
-/** @return the total number of seconds that this time consists of */
+
double
Time::as_seconds () const
{
return h * 3600 + m * 60 + s + double(e) / tcr;
}
-/** @param tcr_ New timecode rate.
- * @return A new Time which is this time at the spcified new timecode rate.
- */
+
Time
Time::rebase (int tcr_) const
{
/*
- Copyright (C) 2012-2015 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2021 Carl Hetherington <cth@carlh.net>
This file is part of libdcp.
files in the program, then also delete it here.
*/
+
/** @file src/dcp_time.h
- * @brief Time class.
+ * @brief Time class
*/
+
#ifndef LIBDCP_TIME_H
#define LIBDCP_TIME_H
+
#include "types.h"
#include <boost/optional.hpp>
#include <stdint.h>
#include <string>
#include <iostream>
+
namespace dcp {
+
class Time;
+
extern bool operator== (Time const & a, Time const & b);
extern bool operator!= (Time const & a, Time const & b);
extern bool operator<= (Time const & a, Time const & b);
extern Time operator- (Time a, Time b);
extern float operator/ (Time a, Time const & b);
+
/** @class Time
* @brief A representation of time within a DCP.
*/
{
public:
/** Construct a zero Time */
- Time () : h (0), m (0), s (0), e (0), tcr (1) {}
+ Time () {}
/** Construct a Time.
* @param frame Frame index (starting from 0).
, tcr (tcr_)
{}
+ /** Construct a Time from a number of seconds and a timecode rate
+ *
+ * @param seconds A number of seconds
+ * @param tcr_ Timecode rate
+ */
Time (double seconds, int tcr);
+ /** @param time String of the form
+ * HH:MM:SS:EE for SMPTE
+ * HH:MM:SS:E[E[E]] or HH:MM:SS.s[s[s]] for Interop
+ * where HH are hours, MM minutes, SS seconds, EE editable units and
+ * sss millseconds.
+ *
+ * @param tcr_ Timecode rate if this is a SMPTE time, otherwise empty for an Interop time
+ */
Time (std::string time, boost::optional<int> tcr);
- int h; ///< hours
- int m; ///< minutes
- int s; ///< seconds
- int e; ///< editable units (where 1 editable unit is 1 / tcr_ seconds)
- int tcr; ///< timecode rate: the number of editable units per second.
+ int h = 0; ///< hours
+ int m = 0; ///< minutes
+ int s = 0; ///< seconds
+ int e = 0; ///< editable units (where 1 editable unit is 1 / tcr_ seconds)
+ int tcr = 1; ///< timecode rate: the number of editable units per second.
+ /** @return A string of the form h:m:s:e padded as in 00:00:00:000 (for Interop) or 00:00:00:00 (for SMPTE) */
std::string as_string (Standard standard) const;
+
+ /** @return the total number of seconds that this time consists of */
double as_seconds () const;
+
+ /** @param tcr_ Timecode rate with which the return value should be counted
+ * @return the total number of editable units that this time consists of at the specified timecode rate, rounded up
+ * to the nearest editable unit. For example, as_editable_units (24) returns the total time in frames at 24fps.
+ */
int64_t as_editable_units (int tcr_) const;
+
+ /** @param tcr_ New timecode rate
+ * @return A new Time which is this time at the spcified new timecode rate
+ */
Time rebase (int tcr_) const;
Time& operator+= (Time const & o) {
void set (double seconds, int tcr);
};
+
}
+
#endif
/*
- Copyright (C) 2013-2017 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2013-2021 Carl Hetherington <cth@carlh.net>
This file is part of libdcp.
files in the program, then also delete it here.
*/
+
+/** @file src/decrypted_kdm.cc
+ * @brief DecryptedKDM class
+ */
+
+
#include "decrypted_kdm.h"
#include "decrypted_kdm_key.h"
#include "encrypted_kdm.h"
#include <openssl/pem.h>
#include <openssl/err.h>
+
using std::list;
using std::vector;
using std::string;
using boost::optional;
using namespace dcp;
+
/* Magic value specified by SMPTE S430-1-2006 */
static uint8_t smpte_structure_id[] = { 0xf1, 0xdc, 0x12, 0x44, 0x60, 0x16, 0x9a, 0x0e, 0x85, 0xbc, 0x30, 0x06, 0x42, 0xf8, 0x66, 0xab };
+
static void
put (uint8_t ** d, string s)
{
(*d) += s.length();
}
+
static void
put (uint8_t ** d, uint8_t const * s, int N)
{
(*d) += N;
}
+
void
DecryptedKDM::put_uuid (uint8_t ** d, string id)
{
*d += 16;
}
+
string
DecryptedKDM::get_uuid (unsigned char ** p)
{
return buffer;
}
+
static string
get (uint8_t ** p, int N)
{
return g;
}
+
DecryptedKDM::DecryptedKDM (EncryptedKDM const & kdm, string private_key)
{
/* Read the private key */
- BIO* bio = BIO_new_mem_buf (const_cast<char *> (private_key.c_str ()), -1);
+ auto bio = BIO_new_mem_buf (const_cast<char *>(private_key.c_str()), -1);
if (!bio) {
throw MiscError ("could not create memory BIO");
}
- RSA* rsa = PEM_read_bio_RSAPrivateKey (bio, 0, 0, 0);
+ auto rsa = PEM_read_bio_RSAPrivateKey (bio, 0, 0, 0);
if (!rsa) {
throw FileError ("could not read RSA private key file", private_key, errno);
}
int const cipher_value_len = base64_decode (i, cipher_value, sizeof (cipher_value));
/* Decrypt it */
- unsigned char * decrypted = new unsigned char[RSA_size(rsa)];
+ auto decrypted = new unsigned char[RSA_size(rsa)];
int const decrypted_len = RSA_private_decrypt (cipher_value_len, cipher_value, decrypted, rsa, RSA_PKCS1_OAEP_PADDING);
if (decrypted_len == -1) {
delete[] decrypted;
_issue_date = kdm.issue_date ();
}
+
DecryptedKDM::DecryptedKDM (
LocalTime not_valid_before,
LocalTime not_valid_after,
}
+
DecryptedKDM::DecryptedKDM (
string cpl_id,
map<shared_ptr<const ReelMXF>, Key> keys,
}
}
+
DecryptedKDM::DecryptedKDM (
shared_ptr<const CPL> cpl,
Key key,
}
}
-/** @param type (MDIK, MDAK etc.)
- * @param key_id Key ID.
- * @param key The actual symmetric key.
- * @param cpl_id ID of CPL that the key is for.
- */
+
void
DecryptedKDM::add_key (optional<string> type, string key_id, Key key, string cpl_id, Standard standard)
{
_keys.push_back (DecryptedKDMKey (type, key_id, key, cpl_id, standard));
}
+
void
DecryptedKDM::add_key (DecryptedKDMKey key)
{
_keys.push_back (key);
}
+
EncryptedKDM
DecryptedKDM::encrypt (
shared_ptr<const CertificateChain> signer,
/*
- Copyright (C) 2013-2018 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2013-2021 Carl Hetherington <cth@carlh.net>
This file is part of libdcp.
files in the program, then also delete it here.
*/
-#ifndef LIBDCP_DECRYPTED_KDM_H
-#define LIBDCP_DECRYPTED_KDM_H
/** @file src/decrypted_kdm.h
- * @brief DecryptedKDM class.
+ * @brief DecryptedKDM class
*/
+
+#ifndef LIBDCP_DECRYPTED_KDM_H
+#define LIBDCP_DECRYPTED_KDM_H
+
+
#include "key.h"
#include "local_time.h"
#include "decrypted_kdm_key.h"
#include <boost/filesystem.hpp>
#include <boost/optional.hpp>
+
class decrypted_kdm_test;
+
namespace dcp {
+
class DecryptedKDMKey;
class EncryptedKDM;
class CertificateChain;
class CPL;
class ReelMXF;
+
/** @class DecryptedKDM
- * @brief A decrypted KDM.
+ * @brief A decrypted KDM
*
* This is a KDM that has either been decrypted by a target private key, or one which
* has been created (by some other means) ready for encryption later.
boost::optional<int> disable_forensic_marking_audio
) const;
+ /** @param type (MDIK, MDAK etc.)
+ * @param key_id Key ID
+ * @param key The actual symmetric key
+ * @param cpl_id ID of CPL that the key is for
+ */
void add_key (boost::optional<std::string> type, std::string key_id, Key key, std::string cpl_id, Standard standard);
+
void add_key (DecryptedKDMKey key);
/** @return This KDM's (decrypted) keys, which could be used to decrypt assets. */
std::vector<DecryptedKDMKey> _keys;
};
+
}
+
#endif
/*
- Copyright (C) 2013-2014 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2013-2021 Carl Hetherington <cth@carlh.net>
This file is part of libdcp.
files in the program, then also delete it here.
*/
+
+/** @file src/decrypted_kdm_key.cc
+ * @brief DecryptedKDMKey class
+ */
+
+
#include "decrypted_kdm_key.h"
+
using namespace dcp;
+
bool
dcp::operator== (dcp::DecryptedKDMKey const & a, dcp::DecryptedKDMKey const & b)
{
/*
- Copyright (C) 2013-2014 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2013-2021 Carl Hetherington <cth@carlh.net>
This file is part of libdcp.
files in the program, then also delete it here.
*/
+
/** @file src/decrypted_kdm_key.h
* @brief DecryptedKDMKey class
*/
+
#ifndef LIBDCP_DECRYPTED_KDM_KEY_H
#define LIBDCP_DECRYPTED_KDM_KEY_H
+
#include "key.h"
#include "types.h"
#include <boost/optional.hpp>
+
namespace dcp {
+
/** @class DecryptedKDMKey
- * @brief An un- or de-crypted key from a KDM.
+ * @brief An un- or de-crypted key from a KDM
*/
class DecryptedKDMKey
{
Standard _standard;
};
+
bool operator== (DecryptedKDMKey const &, DecryptedKDMKey const &);
+
}
+
#endif
files in the program, then also delete it here.
*/
+
+/** @file src/encrypted_kdm.cc
+ * @brief EncryptedKDM class
+ */
+
+
#include "encrypted_kdm.h"
#include "util.h"
#include "certificate_chain.h"
#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/format.hpp>
+
using std::list;
using std::vector;
using std::string;
using boost::starts_with;
using namespace dcp;
+
namespace dcp {
+
/** Namespace for classes used to hold our data; they are internal to this .cc file */
namespace data {
+
class Signer
{
public:
string x509_serial_number;
};
+
class X509Data
{
public:
std::string x509_certificate;
};
+
class Reference
{
public:
string digest_value;
};
+
class SignedInfo
{
public:
Reference authenticated_private;
};
+
class Signature
{
public:
vector<X509Data> x509_data;
};
+
class AuthenticatedPrivate
{
public:
vector<string> encrypted_key;
};
+
class TypedKeyId
{
public:
void as_xml (xmlpp::Element* node) const
{
- xmlpp::Element* type = node->add_child("KeyType");
+ auto type = node->add_child("KeyType");
type->add_child_text (key_type);
node->add_child("KeyId")->add_child_text ("urn:uuid:" + key_id);
/* XXX: this feels like a bit of a hack */
string key_id;
};
+
class KeyIdList
{
public:
vector<TypedKeyId> typed_key_id;
};
+
class AuthorizedDeviceInfo
{
public:
std::vector<string> certificate_thumbprints;
};
+
class X509IssuerSerial
{
public:
string x509_serial_number;
};
+
class Recipient
{
public:
string x509_subject_name;
};
+
class KDMRequiredExtensions
{
public:
static const string audio_disable;
};
+
const string KDMRequiredExtensions::picture_disable = "http://www.smpte-ra.org/430-1/2006/KDM#mrkflg-picture-disable";
const string KDMRequiredExtensions::audio_disable = "http://www.smpte-ra.org/430-1/2006/KDM#mrkflg-audio-disable";
+
class RequiredExtensions
{
public:
KDMRequiredExtensions kdm_required_extensions;
};
+
class AuthenticatedPublic
{
public:
RequiredExtensions required_extensions;
};
+
/** Class to describe our data. We use a class hierarchy as it's a bit nicer
* for XML data than a flat description.
*/
Signature signature;
};
+
}
}
+
EncryptedKDM::EncryptedKDM (string s)
{
try {
}
}
-/** @param trusted_devices Trusted device thumbprints */
+
EncryptedKDM::EncryptedKDM (
shared_ptr<const CertificateChain> signer,
Certificate recipient,
* DCI_SPECIFIC as specified Yes
*/
- data::AuthenticatedPublic& aup = _data->authenticated_public;
+ auto& aup = _data->authenticated_public;
aup.signer.x509_issuer_name = signer->leaf().issuer ();
aup.signer.x509_serial_number = signer->leaf().serial ();
aup.annotation_text = annotation_text;
_data->signature = data::Signature (signed_doc->node_child ("Signature"));
}
+
EncryptedKDM::EncryptedKDM (EncryptedKDM const & other)
: _data (new data::EncryptedKDMData (*other._data))
{
}
+
EncryptedKDM &
EncryptedKDM::operator= (EncryptedKDM const & other)
{
return *this;
}
+
EncryptedKDM::~EncryptedKDM ()
{
delete _data;
}
+
void
EncryptedKDM::as_xml (boost::filesystem::path path) const
{
}
}
+
string
EncryptedKDM::as_xml () const
{
return _data->as_xml()->write_to_string ("UTF-8");
}
+
vector<string>
EncryptedKDM::keys () const
{
return _data->authenticated_private.encrypted_key;
}
+
string
EncryptedKDM::id () const
{
return _data->authenticated_public.message_id;
}
+
optional<string>
EncryptedKDM::annotation_text () const
{
return _data->authenticated_public.annotation_text;
}
+
string
EncryptedKDM::content_title_text () const
{
return _data->authenticated_public.required_extensions.kdm_required_extensions.content_title_text;
}
+
string
EncryptedKDM::cpl_id () const
{
return _data->authenticated_public.required_extensions.kdm_required_extensions.composition_playlist_id;
}
+
string
EncryptedKDM::issue_date () const
{
return _data->authenticated_public.issue_date;
}
+
LocalTime
EncryptedKDM::not_valid_before () const
{
return _data->authenticated_public.required_extensions.kdm_required_extensions.not_valid_before;
}
+
LocalTime
EncryptedKDM::not_valid_after () const
{
return _data->authenticated_public.required_extensions.kdm_required_extensions.not_valid_after;
}
+
string
EncryptedKDM::recipient_x509_subject_name () const
{
return _data->authenticated_public.required_extensions.kdm_required_extensions.recipient.x509_subject_name;
}
+
CertificateChain
EncryptedKDM::signer_certificate_chain () const
{
return chain;
}
+
bool
dcp::operator== (EncryptedKDM const & a, EncryptedKDM const & b)
{
/*
- Copyright (C) 2013-2016 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2013-2021 Carl Hetherington <cth@carlh.net>
This file is part of libdcp.
files in the program, then also delete it here.
*/
+
/** @file src/encrypted_kdm.h
- * @brief EncryptedKDM class.
+ * @brief EncryptedKDM class
*/
+
#ifndef LIBDCP_ENCRYPTED_KDM_H
#define LIBDCP_ENCRYPTED_KDM_H
+
#include "local_time.h"
#include "types.h"
#include <boost/filesystem.hpp>
#include <boost/optional.hpp>
#include <boost/date_time/local_time/local_time.hpp>
+
namespace cxml {
class Node;
}
+
namespace dcp {
+
namespace data {
class EncryptedKDMData;
}
+
class CertificateChain;
class Certificate;
+
/** @class EncryptedKDM
- * @brief An encrypted KDM.
+ * @brief An encrypted KDM
*
* This is a KDM whose keys are encrypted using the target projector's private key.
* An EncryptedKDM object can be initialised from a KDM XML file, or created from
std::vector<std::string> keys
);
- data::EncryptedKDMData* _data;
+ data::EncryptedKDMData* _data = nullptr;
};
+
extern bool operator== (EncryptedKDM const & a, EncryptedKDM const & b);
}
+
#endif
/*
- Copyright (C) 2014-2020 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2014-2021 Carl Hetherington <cth@carlh.net>
This file is part of libdcp.
files in the program, then also delete it here.
*/
+
/** @file src/exceptions.cc
- * @brief Exceptions thrown by libdcp.
+ * @brief Exceptions thrown by libdcp
*/
+
#include "exceptions.h"
#include "compose.hpp"
+
using std::string;
using std::runtime_error;
using boost::optional;
using namespace dcp;
+
FileError::FileError (string message, boost::filesystem::path filename, int number)
: runtime_error (String::compose ("%1 (%2) (error %3)", message, filename.string(), number))
, _filename (filename)
}
+
UnresolvedRefError::UnresolvedRefError (string id)
: runtime_error (String::compose ("Unresolved reference to asset id %1", id))
{
}
+
TimeFormatError::TimeFormatError (string bad_time)
: runtime_error (String::compose ("Bad time string %1", bad_time))
{
}
+
BadContentKindError::BadContentKindError (string content_kind)
: ReadError (String::compose("Bad content kind '%1'", content_kind))
{
}
+
NotEncryptedError::NotEncryptedError (string const & what)
: runtime_error (String::compose ("%1 is not encrypted", what))
{
}
+
KDMDecryptionError::KDMDecryptionError (std::string message, int cipher_length, int modulus_dmax)
: runtime_error (String::compose ("Could not decrypt KDM (%1) (%2/%3)", message, cipher_length, modulus_dmax))
{
}
+
KDMFormatError::KDMFormatError (std::string message)
: runtime_error (String::compose ("Could not parse KDM (%1)", message))
{
}
+
CertificateChainError::CertificateChainError (string message)
: runtime_error (message)
{
}
+
ReadError::ReadError (string message, string detail)
: runtime_error(String::compose("%1 (%2)", message, detail))
, _message(message)
}
+
MissingSubtitleImageError::MissingSubtitleImageError (string id)
: runtime_error (String::compose("Could not load image for subtitle %1", id))
{
}
+
BadKDMDateError::BadKDMDateError (bool starts_too_early)
: runtime_error (
starts_too_early ?
/*
- Copyright (C) 2015 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2015-2021 Carl Hetherington <cth@carlh.net>
This file is part of libdcp.
files in the program, then also delete it here.
*/
+
/** @file src/font_asset.cc
- * @brief FontAsset class.
+ * @brief FontAsset class
*/
+
#include "font_asset.h"
-using std::string;
+using std::string;
using namespace dcp;
+
FontAsset::FontAsset (string id, boost::filesystem::path file)
: Asset (id, file)
{
}
+
string
FontAsset::static_pkl_type (Standard)
{
/*
- Copyright (C) 2015 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2015-2021 Carl Hetherington <cth@carlh.net>
This file is part of libdcp.
files in the program, then also delete it here.
*/
+
/** @file src/font_asset.h
- * @brief FontAsset class.
+ * @brief FontAsset class
*/
+
#include "asset.h"
+
namespace dcp {
+
/** @class FontAsset
* @brief A (truetype) font asset for subtitles in an Interop DCP.
*/
}
};
+
}
*/
+/** @file src/frame.h
+ * @brief Frame class
+ */
+
+
#ifndef LIBDCP_FRAME_H
#define LIBDCP_FRAME_H
Frame (R* reader, int n, std::shared_ptr<const DecryptionContext> c)
{
/* XXX: unfortunate guesswork on this buffer size */
- _buffer.reset(new B(Kumu::Megabyte));
+ _buffer = std::make_shared<B>(Kumu::Megabyte);
if (ASDCP_FAILURE(reader->ReadFrame(n, *_buffer, c->context(), c->hmac()))) {
boost::throw_exception (ReadError ("could not read frame"));
/*
- Copyright (C) 2020 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2020-2021 Carl Hetherington <cth@carlh.net>
This file is part of libdcp.
*/
+/** @file src/fsk.cc
+ * @brief FSK class
+ */
+
+
#include "fsk.h"
#include <iostream>
FSK::FSK ()
- : _data_position (0)
- , _sample_position (0)
- , _last_polarity (false)
- , _last_bit (false)
{
}
*/
+/** @file src/fsk.h
+ * @brief FSK class
+ */
+
+
#include <stdint.h>
#include <vector>
private:
std::vector<bool> _data;
/** current offset into _data */
- int _data_position;
+ int _data_position = 0;
/** current sample number of the current bit (0-3) */
- int _sample_position;
+ int _sample_position = 0;
/** polarity of the last bit to be written (false for -ve, true for +ve) */
- bool _last_polarity;
+ bool _last_polarity = false;
/** value of the last bit to be written */
- bool _last_bit;
+ bool _last_bit = false;
};
+
}
GammaTransferFunction::make_lut (int bit_depth, bool inverse) const
{
int const bit_length = int(std::pow(2.0f, bit_depth));
- double* lut = new double[bit_length];
+ auto lut = new double[bit_length];
double const gamma = inverse ? (1 / _gamma) : _gamma;
for (int i = 0; i < bit_length; ++i) {
lut[i] = pow(double(i) / (bit_length - 1), gamma);
/*
- Copyright (C) 2016 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2016-2021 Carl Hetherington <cth@carlh.net>
This file is part of libdcp.
files in the program, then also delete it here.
*/
+
/** @file src/identity_transfer_function.cc
- * @brief IdentityTransferFunction class.
+ * @brief IdentityTransferFunction class
*/
+
#include "identity_transfer_function.h"
#include <cmath>
+
using std::pow;
using std::shared_ptr;
using std::dynamic_pointer_cast;
using namespace dcp;
+
double *
IdentityTransferFunction::make_lut (int bit_depth, bool) const
{
int const bit_length = int(std::pow(2.0f, bit_depth));
- double* lut = new double[bit_length];
+ auto lut = new double[bit_length];
for (int i = 0; i < bit_length; ++i) {
lut[i] = double(i) / (bit_length - 1);
}
return lut;
}
+
bool
IdentityTransferFunction::about_equal (shared_ptr<const TransferFunction> other, double) const
{
- shared_ptr<const IdentityTransferFunction> o = dynamic_pointer_cast<const IdentityTransferFunction> (other);
+ auto o = dynamic_pointer_cast<const IdentityTransferFunction>(other);
return static_cast<bool>(o);
}
/*
- Copyright (C) 2016 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2016-2021 Carl Hetherington <cth@carlh.net>
This file is part of libdcp.
files in the program, then also delete it here.
*/
+
/** @file src/identity_transfer_function.h
- * @brief IdentityTransferFunction class.
+ * @brief IdentityTransferFunction class
*/
+
#include "transfer_function.h"
+
namespace dcp {
+
class IdentityTransferFunction : public TransferFunction
{
public:
double * make_lut (int bit_depth, bool inverse) const;
};
+
}
/*
- Copyright (C) 2012-2015 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2021 Carl Hetherington <cth@carlh.net>
This file is part of libdcp.
files in the program, then also delete it here.
*/
+
+/** @file src/interop_load_font_node.cc
+ * @brief InteropLoadFontNode class
+ */
+
+
#include "interop_load_font_node.h"
#include <libcxml/cxml.h>
+
using std::string;
using std::shared_ptr;
using boost::optional;
using namespace dcp;
+
InteropLoadFontNode::InteropLoadFontNode (string id_, string uri_)
: LoadFontNode (id_)
, uri (uri_)
}
+
InteropLoadFontNode::InteropLoadFontNode (cxml::ConstNodePtr node)
{
- optional<string> x = node->optional_string_attribute ("Id");
+ auto x = node->optional_string_attribute("Id");
if (!x) {
- x = node->optional_string_attribute ("ID");
+ x = node->optional_string_attribute("ID");
}
id = x.get_value_or ("");
uri = node->string_attribute ("URI");
}
+
bool
dcp::operator== (InteropLoadFontNode const & a, InteropLoadFontNode const & b)
{
return a.id == b.id && a.uri == b.uri;
}
+
bool
dcp::operator!= (InteropLoadFontNode const & a, InteropLoadFontNode const & b)
{
/*
- Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2021 Carl Hetherington <cth@carlh.net>
This file is part of libdcp.
files in the program, then also delete it here.
*/
+
+/** @file src/interop_load_font_node.h
+ * @brief InteropLoadFontNode class
+ */
+
+
#include "load_font_node.h"
#include <libcxml/cxml.h>
-#include <memory>
#include <boost/optional.hpp>
+#include <memory>
+
namespace dcp {
+
class InteropLoadFontNode : public LoadFontNode
{
public:
std::string uri;
};
+
bool operator== (InteropLoadFontNode const & a, InteropLoadFontNode const & b);
bool operator!= (InteropLoadFontNode const & a, InteropLoadFontNode const & b);
+
}
files in the program, then also delete it here.
*/
+
+/** @file src/interop_subtitle_asset.cc
+ * @brief InteropSubtitleAsset class
+ */
+
+
#include "interop_subtitle_asset.h"
#include "interop_load_font_node.h"
#include "subtitle_asset_internal.h"
#include <cmath>
#include <cstdio>
+
using std::list;
using std::string;
using std::cout;
using boost::optional;
using namespace dcp;
+
InteropSubtitleAsset::InteropSubtitleAsset (boost::filesystem::path file)
: SubtitleAsset (file)
{
_raw_xml = dcp::file_to_string (file);
- shared_ptr<cxml::Document> xml (new cxml::Document ("DCSubtitle"));
+ auto xml = make_shared<cxml::Document>("DCSubtitle");
xml->read_file (file);
_id = xml->string_child ("SubtitleID");
_reel_number = xml->string_child ("ReelNumber");
/* Now we need to drop down to xmlpp */
vector<ParseState> ps;
- xmlpp::Node::NodeList c = xml->node()->get_children ();
- for (xmlpp::Node::NodeList::const_iterator i = c.begin(); i != c.end(); ++i) {
- xmlpp::Element const * e = dynamic_cast<xmlpp::Element const *> (*i);
+ for (auto i: xml->node()->get_children()) {
+ auto e = dynamic_cast<xmlpp::Element const *>(i);
if (e && (e->get_name() == "Font" || e->get_name() == "Subtitle")) {
parse_subtitles (e, ps, optional<int>(), Standard::INTEROP);
}
}
}
+
InteropSubtitleAsset::InteropSubtitleAsset ()
{
}
+
string
InteropSubtitleAsset::xml_as_string () const
{
xmlpp::Document doc;
- xmlpp::Element* root = doc.create_root_node ("DCSubtitle");
+ auto root = doc.create_root_node ("DCSubtitle");
root->set_attribute ("Version", "1.0");
root->add_child("SubtitleID")->add_child_text (_id);
return doc.write_to_string ("UTF-8");
}
+
void
InteropSubtitleAsset::add_font (string load_id, dcp::ArrayData data)
{
_fonts.push_back (Font(load_id, make_uuid(), data));
- string const uri = String::compose("font_%1.ttf", _load_font_nodes.size());
+ auto const uri = String::compose("font_%1.ttf", _load_font_nodes.size());
_load_font_nodes.push_back (shared_ptr<InteropLoadFontNode>(new InteropLoadFontNode(load_id, uri)));
}
+
bool
InteropSubtitleAsset::equals (shared_ptr<const Asset> other_asset, EqualityOptions options, NoteHandler note) const
{
return false;
}
- shared_ptr<const InteropSubtitleAsset> other = dynamic_pointer_cast<const InteropSubtitleAsset> (other_asset);
+ auto other = dynamic_pointer_cast<const InteropSubtitleAsset> (other_asset);
if (!other) {
return false;
}
return true;
}
+
vector<shared_ptr<LoadFontNode>>
InteropSubtitleAsset::load_font_nodes () const
{
return lf;
}
-/** Write this content to an XML file with its fonts alongside */
+
void
InteropSubtitleAsset::write (boost::filesystem::path p) const
{
- FILE* f = fopen_boost (p, "w");
+ auto f = fopen_boost (p, "w");
if (!f) {
throw FileError ("Could not open file for writing", p, -1);
}
- string const s = xml_as_string ();
+ auto const s = xml_as_string ();
/* length() here gives bytes not characters */
fwrite (s.c_str(), 1, s.length(), f);
fclose (f);
}
}
+
/** Look at a supplied list of assets and find the fonts. Then match these
* fonts up with anything requested by a <LoadFont> so that _fonts contains
* a list of font ID, load ID and data.
}
}
+
void
InteropSubtitleAsset::add_font_assets (vector<shared_ptr<Asset>>& assets)
{
}
}
+
void
InteropSubtitleAsset::write_to_assetmap (xmlpp::Node* node, boost::filesystem::path root) const
{
}
}
+
void
InteropSubtitleAsset::add_to_pkl (shared_ptr<PKL> pkl, boost::filesystem::path root) const
{
/*
- Copyright (C) 2012-2015 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2021 Carl Hetherington <cth@carlh.net>
This file is part of libdcp.
files in the program, then also delete it here.
*/
+
/** @file src/interop_subtitle_asset.h
- * @brief InteropSubtitleAsset class.
+ * @brief InteropSubtitleAsset class
*/
+
#include "subtitle_asset.h"
#include <boost/filesystem.hpp>
+
namespace dcp {
+
class InteropLoadFontNode;
+
/** @class InteropSubtitleAsset
- * @brief A set of subtitles to be read and/or written in the Inter-Op format.
+ * @brief A set of subtitles to be read and/or written in the Inter-Op format
*
* Inter-Op subtitles are sometimes known as CineCanvas.
*/
void add_font (std::string load_id, dcp::ArrayData data);
std::string xml_as_string () const;
+
+ /** Write this content to an XML file with its fonts alongside */
void write (boost::filesystem::path path) const;
+
void resolve_fonts (std::vector<std::shared_ptr<Asset>> assets);
void add_font_assets (std::vector<std::shared_ptr<Asset>>& assets);
void set_font_file (std::string load_id, boost::filesystem::path file);
/*
- Copyright (C) 2012-2015 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2021 Carl Hetherington <cth@carlh.net>
This file is part of libdcp.
*/
+/** @file src/j2k.cc
+ * @brief Methods to encode and decode JPEG2000
+ */
+
+
#include "array_data.h"
#include "j2k.h"
#include "exceptions.h"
#include <cmath>
#include <iostream>
+
using std::min;
using std::pow;
using std::string;
using boost::shared_array;
using namespace dcp;
+
shared_ptr<dcp::OpenJPEGImage>
dcp::decompress_j2k (ArrayData data, int reduce)
{
return dcp::decompress_j2k (data.data(), data.size(), reduce);
}
+
#ifdef LIBDCP_OPENJPEG2
class ReadBuffer
OPJ_SIZE_T _offset;
};
+
static OPJ_SIZE_T
read_function (void* buffer, OPJ_SIZE_T nb_bytes, void* data)
{
return reinterpret_cast<ReadBuffer*>(data)->read (buffer, nb_bytes);
}
+
static void
read_free_function (void* data)
{
throw MiscError (msg);
}
-/** 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 OpenJPEGImage.
- */
+
shared_ptr<dcp::OpenJPEGImage>
dcp::decompress_j2k (uint8_t* data, int64_t size, int reduce)
{
0x20
};
- OPJ_CODEC_FORMAT format = OPJ_CODEC_J2K;
+ auto format = OPJ_CODEC_J2K;
if (size >= int (sizeof (jp2_magic)) && memcmp (data, jp2_magic, sizeof (jp2_magic)) == 0) {
format = OPJ_CODEC_JP2;
}
- opj_codec_t* decoder = opj_create_decompress (format);
+ auto decoder = opj_create_decompress (format);
if (!decoder) {
boost::throw_exception (ReadError ("could not create JPEG2000 decompresser"));
}
parameters.cp_reduce = reduce;
opj_setup_decoder (decoder, ¶meters);
- opj_stream_t* stream = opj_stream_default_create (OPJ_TRUE);
+ auto stream = opj_stream_default_create (OPJ_TRUE);
if (!stream) {
throw MiscError ("could not create JPEG2000 stream");
}
opj_set_error_handler(decoder, decompress_error_callback, 00);
opj_stream_set_read_function (stream, read_function);
- ReadBuffer* buffer = new ReadBuffer (data, size);
+ auto buffer = new ReadBuffer (data, size);
opj_stream_set_user_data (stream, buffer, read_free_function);
opj_stream_set_user_data_length (stream, size);
image->y1 = rint (float(image->y1) / pow (2.0f, reduce));
return shared_ptr<OpenJPEGImage> (new OpenJPEGImage (image));
}
+
#endif
+
#ifdef LIBDCP_OPENJPEG1
-/** 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 XYZ image.
- */
+
shared_ptr<dcp::OpenJPEGImage>
dcp::decompress_j2k (uint8_t* data, int64_t size, int reduce)
{
- opj_dinfo_t* decoder = opj_create_decompress (CODEC_J2K);
+ auto decoder = opj_create_decompress (CODEC_J2K);
opj_dparameters_t parameters;
opj_set_default_decoder_parameters (¶meters);
parameters.cp_reduce = reduce;
opj_setup_decoder (decoder, ¶meters);
- opj_cio_t* cio = opj_cio_open ((opj_common_ptr) decoder, data, size);
- opj_image_t* image = opj_decode (decoder, cio);
+ auto cio = opj_cio_open ((opj_common_ptr) decoder, data, size);
+ auto image = opj_decode (decoder, cio);
if (!image) {
opj_destroy_decompress (decoder);
opj_cio_close (cio);
}
#endif
+
#ifdef LIBDCP_OPENJPEG2
+
class WriteBuffer
{
public:
/* XXX: is there a better strategy for this? */
#define MAX_J2K_SIZE (1024 * 1024 * 2)
WriteBuffer ()
- : _data (shared_array<uint8_t> (new uint8_t[MAX_J2K_SIZE]), MAX_J2K_SIZE)
+ : _data (shared_array<uint8_t>(new uint8_t[MAX_J2K_SIZE]), MAX_J2K_SIZE)
, _offset (0)
{
_data.set_size (0);
DCP_ASSERT ((_offset + nb_bytes) < MAX_J2K_SIZE);
memcpy (_data.data() + _offset, buffer, nb_bytes);
_offset += nb_bytes;
- if (_offset > OPJ_SIZE_T (_data.size())) {
+ if (_offset > OPJ_SIZE_T(_data.size())) {
_data.set_size (_offset);
}
return nb_bytes;
OPJ_SIZE_T _offset;
};
+
static OPJ_SIZE_T
write_function (void* buffer, OPJ_SIZE_T nb_bytes, void* data)
{
- return reinterpret_cast<WriteBuffer*>(data)->write (buffer, nb_bytes);
+ return reinterpret_cast<WriteBuffer*>(data)->write(buffer, nb_bytes);
}
+
static void
write_free_function (void* data)
{
delete reinterpret_cast<WriteBuffer*>(data);
}
+
static OPJ_BOOL
seek_function (OPJ_OFF_T nb_bytes, void* data)
{
- return reinterpret_cast<WriteBuffer*>(data)->seek (nb_bytes);
+ return reinterpret_cast<WriteBuffer*>(data)->seek(nb_bytes);
+
}
-/** @xyz Picture to compress. Parts of xyz's data WILL BE OVERWRITTEN by libopenjpeg so xyz cannot be re-used
- * after this call; see opj_j2k_encode where if l_reuse_data is false it will set l_tilec->data = l_img_comp->data.
- */
+
ArrayData
dcp::compress_j2k (shared_ptr<const OpenJPEGImage> xyz, int bandwidth, int frames_per_second, bool threed, bool fourk, string comment)
{
/* get a J2K compressor handle */
- opj_codec_t* encoder = opj_create_compress (OPJ_CODEC_J2K);
- if (encoder == 0) {
+ auto encoder = opj_create_compress (OPJ_CODEC_J2K);
+ if (encoder == nullptr) {
throw MiscError ("could not create JPEG2000 encoder");
}
/* Setup the encoder parameters using the current image and user parameters */
opj_setup_encoder (encoder, ¶meters, xyz->opj_image());
- opj_stream_t* stream = opj_stream_default_create (OPJ_FALSE);
+ auto stream = opj_stream_default_create (OPJ_FALSE);
if (!stream) {
opj_destroy_codec (encoder);
free (parameters.cp_comment);
return enc;
}
+
#endif
+
#ifdef LIBDCP_OPENJPEG1
+
ArrayData
dcp::compress_j2k (shared_ptr<const OpenJPEGImage> xyz, int bandwidth, int frames_per_second, bool threed, bool fourk)
{
int const max_comp_size = max_cs_len / 1.25;
/* get a J2K compressor handle */
- opj_cinfo_t* cinfo = opj_create_compress (CODEC_J2K);
- if (cinfo == 0) {
+ auto cinfo = opj_create_compress (CODEC_J2K);
+ if (cinfo == nullptr) {
throw MiscError ("could not create JPEG2000 encoder");
}
cinfo->event_mgr = 0;
/* Setup the encoder parameters using the current image and user parameters */
- opj_setup_encoder (cinfo, ¶meters, xyz->opj_image ());
+ opj_setup_encoder (cinfo, ¶meters, xyz->opj_image());
- opj_cio_t* cio = opj_cio_open ((opj_common_ptr) cinfo, 0, 0);
- if (cio == 0) {
+ auto cio = opj_cio_open ((opj_common_ptr) cinfo, 0, 0);
+ if (cio == nullptr) {
opj_destroy_compress (cinfo);
throw MiscError ("could not open JPEG2000 stream");
}
/*
- Copyright (C) 2012-2016 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2021 Carl Hetherington <cth@carlh.net>
This file is part of libdcp.
*/
+/** @file src/j2k.h
+ * @brief Methods to encode and decode JPEG2000
+ */
+
+
#include "array_data.h"
#include <memory>
#include <stdint.h>
+
namespace dcp {
+
class OpenJPEGImage;
+
extern std::shared_ptr<OpenJPEGImage> decompress_j2k (uint8_t* data, int64_t size, int reduce);
+
+/** 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 OpenJPEGImage
+ */
extern std::shared_ptr<OpenJPEGImage> decompress_j2k (ArrayData data, int reduce);
+
+/** @xyz Picture to compress. Parts of xyz's data WILL BE OVERWRITTEN by libopenjpeg so xyz cannot be re-used
+ * after this call; see opj_j2k_encode where if l_reuse_data is false it will set l_tilec->data = l_img_comp->data.
+ */
extern ArrayData compress_j2k (std::shared_ptr<const OpenJPEGImage>, int bandwith, int frames_per_second, bool threed, bool fourk, std::string comment = "libdcp");
+
}
*/
+/** @file src/language_tag.cc
+ * @brief LanguageTag class
+ */
+
+
#include "compose.hpp"
#include "dcp_assert.h"
#include "exceptions.h"
}
}
- return optional<LanguageTag::SubtagData>();
+ return {};
}
throw LanguageTagError("No language set up");
}
- string s = _language->subtag();
+ auto s = _language->subtag();
if (_script) {
s += "-" + _script->subtag();
d += language->description;
if (_script) {
- optional<SubtagData> script = get_subtag_data (SubtagType::SCRIPT, _script->subtag());
+ auto script = get_subtag_data (SubtagType::SCRIPT, _script->subtag());
DCP_ASSERT (script);
d += " written using the " + script->description + " script";
}
if (_region) {
- optional<SubtagData> region = get_subtag_data (SubtagType::REGION, _region->subtag());
+ auto region = get_subtag_data (SubtagType::REGION, _region->subtag());
DCP_ASSERT (region);
d += " for " + region->description;
}
for (auto const& i: _extlangs) {
- optional<SubtagData> extlang = get_subtag_data (SubtagType::EXTLANG, i.subtag());
+ auto extlang = get_subtag_data (SubtagType::EXTLANG, i.subtag());
DCP_ASSERT (extlang);
d += ", " + extlang->description;
}
return "Extended";
}
- return "";
+ return {};
}
bool
return find_in_list(extlang_list, subtag);
}
- return optional<LanguageTag::SubtagData>();
+ return {};
}
optional<string>
LanguageTag::get_subtag_description (LanguageTag::SubtagType type, string subtag)
{
- optional<SubtagData> data = get_subtag_data (type, subtag);
+ auto data = get_subtag_data (type, subtag);
if (!data) {
- return optional<string>();
+ return {};
}
return data->description;
void
load_language_tag_list (boost::filesystem::path tags_directory, string name, vector<LanguageTag::SubtagData>& list)
{
- FILE* f = fopen_boost (tags_directory / name, "r");
+ auto f = fopen_boost (tags_directory / name, "r");
if (!f) {
throw FileError ("Could not open tags file", tags_directory / name, errno);
}
files in the program, then also delete it here.
*/
+
+/** @file src/language_tag.cc
+ * @brief LanguageTag class
+ */
+
+
#ifndef LIBDCP_LANGUAGE_TAG_H
#define LIBDCP_LANGUAGE_TAG_H
std::vector<ExtlangSubtag> _extlangs;
};
+
extern bool operator==(dcp::LanguageTag const& a, dcp::LanguageTag const& b);
extern std::ostream& operator<<(std::ostream& os, dcp::LanguageTag const& tag);
extern void load_language_tag_lists (boost::filesystem::path tags_directory);
+
}
#endif
/*
- Copyright (C) 2012-2015 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2021 Carl Hetherington <cth@carlh.net>
This file is part of libdcp.
files in the program, then also delete it here.
*/
+
/** @file src/load_font_node.h
- * @brief LoadFontNode class.
+ * @brief LoadFontNode class
*/
+
#include <string>
+
namespace dcp {
+
/** @class LoadFontNode
- * @brief Parser for LoadFont nodes from subtitle XML.
+ * @brief Parser for LoadFont nodes from subtitle XML
*/
class LoadFontNode
{
/*
- Copyright (C) 2014-2020 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2014-2021 Carl Hetherington <cth@carlh.net>
This file is part of libdcp.
files in the program, then also delete it here.
*/
+
/** @file src/local_time.cc
- * @brief LocalTime class.
+ * @brief LocalTime class
*/
+
#include "local_time.h"
#include "exceptions.h"
#include "dcp_assert.h"
#include <boost/date_time/gregorian/gregorian.hpp>
#include <cstdio>
+
using std::string;
using std::ostream;
using boost::lexical_cast;
using namespace dcp;
-/** Construct a LocalTime from the current time */
+
LocalTime::LocalTime ()
{
- time_t now = time (0);
- struct tm* tm = localtime (&now);
+ auto now = time (0);
+ auto tm = localtime (&now);
set (tm);
set_local_time_zone ();
}
+
LocalTime::LocalTime (struct tm t)
{
set (&t);
set_local_time_zone ();
}
+
void
LocalTime::set (struct tm const * tm)
{
_millisecond = 0;
}
-/** Construct a LocalTime from a boost::posix_time::ptime using the local
- * time zone.
- */
+
LocalTime::LocalTime (boost::posix_time::ptime t)
{
set (t);
set_local_time_zone ();
}
+
void
LocalTime::set (boost::posix_time::ptime t)
{
DCP_ASSERT (_millisecond < 1000);
}
-/** Construct a LocalTime from a boost::posix_time::ptime and a time zone offset.
- * @param tz_minute Offset from UTC in minutes; if the timezone is behind UTC this may be negative,
- * e.g. -04:30 would have tz_hour=-1 and tz_minute=-30.
- */
+
LocalTime::LocalTime (boost::posix_time::ptime t, int tz_hour, int tz_minute)
{
set (t);
_tz_minute = tz_minute;
}
+
/** Set our UTC offset to be according to the local time zone */
void
LocalTime::set_local_time_zone ()
{
- boost::posix_time::ptime const utc_now = boost::posix_time::second_clock::universal_time ();
- boost::posix_time::ptime const now = boost::date_time::c_local_adjustor<boost::posix_time::ptime>::utc_to_local (utc_now);
- boost::posix_time::time_duration offset = now - utc_now;
+ auto const utc_now = boost::posix_time::second_clock::universal_time ();
+ auto const now = boost::date_time::c_local_adjustor<boost::posix_time::ptime>::utc_to_local (utc_now);
+ auto offset = now - utc_now;
_tz_hour = offset.hours ();
_tz_minute = offset.minutes ();
}
-/** @param s A string of the form 2013-01-05T18:06:59[.123][+04:00] */
+
LocalTime::LocalTime (string s)
{
/* 2013-01-05T18:06:59 or 2013-01-05T18:06:59.123 or 2013-01-05T18:06:59+04:00 or 2013-01-05T18:06:59.123+04:00 */
throw TimeFormatError (s);
}
- _year = lexical_cast<int> (s.substr (0, 4));
- _month = lexical_cast<int> (s.substr (5, 2));
- _day = lexical_cast<int> (s.substr (8, 2));
- _hour = lexical_cast<int> (s.substr (11, 2));
- _minute = lexical_cast<int> (s.substr (14, 2));
- _second = lexical_cast<int> (s.substr (17, 2));
- _millisecond = with_millisecond ? lexical_cast<int> (s.substr (20, 3)) : 0;
- _tz_hour = with_tz ? lexical_cast<int> (s.substr (tz_pos + 1, 2)) : 0;
- _tz_minute = with_tz ? lexical_cast<int> (s.substr (tz_pos + 4, 2)) : 0;
+ _year = lexical_cast<int>(s.substr(0, 4));
+ _month = lexical_cast<int>(s.substr(5, 2));
+ _day = lexical_cast<int>(s.substr(8, 2));
+ _hour = lexical_cast<int>(s.substr(11, 2));
+ _minute = lexical_cast<int>(s.substr(14, 2));
+ _second = lexical_cast<int>(s.substr(17, 2));
+ _millisecond = with_millisecond ? lexical_cast<int>(s.substr(20, 3)) : 0;
+ _tz_hour = with_tz ? lexical_cast<int>(s.substr(tz_pos + 1, 2)) : 0;
+ _tz_minute = with_tz ? lexical_cast<int>(s.substr(tz_pos + 4, 2)) : 0;
if (with_tz && s[tz_pos] == '-') {
_tz_hour = -_tz_hour;
}
}
-/** @return A string of the form 2013-01-05T18:06:59+04:00 or 2013-01-05T18:06:59.123+04:00 */
+
string
LocalTime::as_string (bool with_millisecond) const
{
return buffer;
}
-/** @return The date in the form YYYY-MM-DD */
+
string
LocalTime::date () const
{
return buffer;
}
-/** @return The time in the form HH:MM:SS or HH:MM:SS.mmm */
+
string
LocalTime::time_of_day (bool with_second, bool with_millisecond) const
{
set (posix_time::ptime(d, posix_time::time_duration(_hour, _minute, _second, _millisecond * 1000)));
}
+
void
LocalTime::add_minutes (int m)
{
set (t);
}
+
bool
LocalTime::operator== (LocalTime const & other) const
{
_tz_hour == other._tz_hour && _tz_minute == other._tz_minute;
}
+
bool
LocalTime::operator< (LocalTime const & other) const
{
return _millisecond < other._millisecond;
}
+
bool
LocalTime::operator!= (LocalTime const & other) const
{
return !(*this == other);
}
+
ostream&
dcp::operator<< (ostream& s, LocalTime const & t)
{
/*
- Copyright (C) 2014-2020 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2014-2021 Carl Hetherington <cth@carlh.net>
This file is part of libdcp.
files in the program, then also delete it here.
*/
+
/** @file src/local_time.h
- * @brief LocalTime class.
+ * @brief LocalTime class
*/
+
#ifndef LIBDCP_LOCAL_TIME_H
#define LIBDCP_LOCAL_TIME_H
+
#include <boost/date_time/posix_time/posix_time.hpp>
#include <string>
+
class local_time_basic_test;
+
namespace dcp {
+
/** @class LocalTime
* @brief A representation of a local time (down to the second), including its offset
* from GMT (equivalent to xs:dateTime).
class LocalTime
{
public:
+ /** Construct a LocalTime from the current time */
LocalTime ();
+
explicit LocalTime (struct tm tm);
+
+ /** Construct a LocalTime from a boost::posix_time::ptime using the local
+ * time zone
+ */
explicit LocalTime (boost::posix_time::ptime);
+
+ /** Construct a LocalTime from a boost::posix_time::ptime and a time zone offset
+ * @param tz_minute Offset from UTC in minutes; if the timezone is behind UTC this may be negative,
+ * e.g. -04:30 would have tz_hour=-1 and tz_minute=-30.
+ */
LocalTime (boost::posix_time::ptime, int tz_hour, int tz_minute);
- explicit LocalTime (std::string);
+ /** @param s A string of the form 2013-01-05T18:06:59[.123][+04:00] */
+ explicit LocalTime (std::string s);
+
+ /** @return A string of the form 2013-01-05T18:06:59+04:00 or 2013-01-05T18:06:59.123+04:00 */
std::string as_string (bool with_millisecond = false) const;
+
+ /** @return The date in the form YYYY-MM-DD */
std::string date () const;
+
+ /** @return The time in the form HH:MM:SS or HH:MM:SS.mmm */
std::string time_of_day (bool with_second, bool with_millisecond) const;
int day () const {
void set_local_time_zone ();
/* Local time */
- int _year; ///< year
- int _month; ///< month number of the year (1-12)
- int _day; ///< day number of the month (1-31)
- int _hour; ///< hour number of the day (0-23)
- int _minute; ///< minute number of the hour (0-59)
- int _second; ///< second number of the minute (0-59)
- int _millisecond; ///< millisecond number of the second (0-999)
-
- int _tz_hour; ///< hours by which this time is offset from UTC; can be negative
+ int _year = 0; ///< year
+ int _month = 0; ///< month number of the year (1-12)
+ int _day = 0; ///< day number of the month (1-31)
+ int _hour = 0; ///< hour number of the day (0-23)
+ int _minute = 0; ///< minute number of the hour (0-59)
+ int _second = 0; ///< second number of the minute (0-59)
+ int _millisecond = 0; ///< millisecond number of the second (0-999)
+
+ int _tz_hour = 0; ///< hours by which this time is offset from UTC; can be negative
/** Minutes by which this time is offset from UTC; if _tz_hour is negative
* this will be either 0 or negative.
*/
- int _tz_minute;
+ int _tz_minute = 0;
};
+
std::ostream&
operator<< (std::ostream& s, LocalTime const & t);
+
}
+
#endif
/*
- Copyright (C) 2016 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2016-2021 Carl Hetherington <cth@carlh.net>
This file is part of libdcp.
files in the program, then also delete it here.
*/
+
+/** @file src/locale_convert.cc
+ * @brief Methods to convert to/from string using the current locale
+ */
+
+
#include "locale_convert.h"
#include <string>
#include <inttypes.h>
+
using std::string;
using std::wstring;
+
template<>
string
dcp::locale_convert (unsigned char x, int, bool)
return buffer;
}
+
template<>
string
dcp::locale_convert (unsigned short int x, int, bool)
return buffer;
}
+
template<>
string
dcp::locale_convert (int x, int, bool)
return buffer;
}
+
template<>
string
dcp::locale_convert (unsigned int x, int, bool)
return buffer;
}
+
template<>
string
dcp::locale_convert (long int x, int, bool)
return buffer;
}
+
template<>
string
dcp::locale_convert (unsigned long int x, int, bool)
return buffer;
}
+
template<>
string
dcp::locale_convert (long long int x, int, bool)
return buffer;
}
+
template<>
string
dcp::locale_convert (unsigned long long int x, int, bool)
return buffer;
}
+
template<>
string
dcp::locale_convert (float x, int precision, bool fixed)
return buffer;
}
+
template<>
string
dcp::locale_convert (double x, int precision, bool fixed)
return buffer;
}
+
template<>
string
dcp::locale_convert (string x, int, bool)
return x;
}
+
template<>
string
dcp::locale_convert (char* x, int, bool)
return x;
}
+
template<>
string
dcp::locale_convert (char const * x, int, bool)
return x;
}
+
template<>
string
dcp::locale_convert (wchar_t const * x, int, bool)
return string (s.begin(), s.end());
}
+
template<>
string
dcp::locale_convert (char x, int, bool)
return s;
}
+
template<>
string
dcp::locale_convert (boost::filesystem::path x, int, bool)
return x.string();
}
+
template<>
unsigned char
dcp::locale_convert (string x, int, bool)
return y;
}
+
template<>
unsigned short int
dcp::locale_convert (string x, int, bool)
return y;
}
+
template<>
unsigned int
dcp::locale_convert (string x, int, bool)
return y;
}
+
template<>
int
dcp::locale_convert (string x, int, bool)
return y;
}
+
template<>
long
dcp::locale_convert (string x, int, bool)
return y;
}
+
template<>
unsigned long
dcp::locale_convert (string x, int, bool)
return y;
}
+
template<>
long long
dcp::locale_convert (string x, int, bool)
return y;
}
+
template<>
unsigned long long
dcp::locale_convert (string x, int, bool)
return y;
}
+
template<>
float
dcp::locale_convert (string x, int, bool)
return y;
}
+
template<>
double
dcp::locale_convert (string x, int, bool)
/*
- Copyright (C) 2016 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2016-2021 Carl Hetherington <cth@carlh.net>
This file is part of libdcp.
files in the program, then also delete it here.
*/
+
+/** @file src/locale_convert.cc
+ * @brief Methods to convert to/from string using the current locale.
+ */
+
+
#ifndef LIBDCP_LOCALE_CONVERT_H
#define LIBDCP_LOCALE_CONVERT_H
+
#include "util.h"
#include <boost/filesystem.hpp>
#include <boost/static_assert.hpp>
#include <string>
#include <cstdio>
+
namespace dcp {
+
template <typename P, typename Q>
P
locale_convert (Q, int precision = 16, bool fixed = false)
double
locale_convert (std::string x, int, bool);
+
}
+
#endif
/*
- Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2021 Carl Hetherington <cth@carlh.net>
This file is part of libdcp.
files in the program, then also delete it here.
*/
+
/** @file src/metadata.cc
- * @brief MXFMetadata class.
+ * @brief MXFMetadata class
*/
+
#include "metadata.h"
#include "util.h"
#include "local_time.h"
#include <iomanip>
#include <time.h>
-using namespace std;
+
using namespace dcp;
+
MXFMetadata::MXFMetadata ()
: company_name ("libdcp")
, product_name ("libdcp")
}
+
void
MXFMetadata::read (ASDCP::WriterInfo const & info)
{
/*
- Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2021 Carl Hetherington <cth@carlh.net>
This file is part of libdcp.
files in the program, then also delete it here.
*/
-#ifndef LIBDCP_METADATA_H
-#define LIBDCP_METADATA_H
/** @file src/metadata.h
* @brief MXFMetadata class.
*/
+
+#ifndef LIBDCP_METADATA_H
+#define LIBDCP_METADATA_H
+
+
#include <string>
+
class utc_offset_to_string_test;
+
namespace ASDCP {
struct WriterInfo;
}
+
namespace dcp
{
+
/** @class MXFMetadata
* @brief Metadata that is written to a MXF file's header
*/
std::string product_version;
};
+
}
+
#endif
/*
- Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2021 Carl Hetherington <cth@carlh.net>
This file is part of libdcp.
files in the program, then also delete it here.
*/
+
+/** @file src/modified_gamma_transfer_function.cc
+ * @brief ModifiedGammaTransferFunction class
+ */
+
+
#include "modified_gamma_transfer_function.h"
#include <cmath>
+
using std::pow;
using std::shared_ptr;
using std::dynamic_pointer_cast;
using namespace dcp;
+
ModifiedGammaTransferFunction::ModifiedGammaTransferFunction (double power, double threshold, double A, double B)
: _power (power)
, _threshold (threshold)
}
+
double *
ModifiedGammaTransferFunction::make_lut (int bit_depth, bool inverse) const
{
if (inverse) {
double const threshold = _threshold / _B;
for (int i = 0; i < bit_length; ++i) {
- double const p = static_cast<double> (i) / (bit_length - 1);
+ double const p = static_cast<double>(i) / (bit_length - 1);
if (p > threshold) {
lut[i] = (1 + _A) * pow (p, 1 / _power) - _A;
} else {
}
} else {
for (int i = 0; i < bit_length; ++i) {
- double const p = static_cast<double> (i) / (bit_length - 1);
+ double const p = static_cast<double>(i) / (bit_length - 1);
if (p > _threshold) {
lut[i] = pow ((p + _A) / (1 + _A), _power);
} else {
return lut;
}
+
bool
ModifiedGammaTransferFunction::about_equal (shared_ptr<const TransferFunction> other, double epsilon) const
{
- shared_ptr<const ModifiedGammaTransferFunction> o = dynamic_pointer_cast<const ModifiedGammaTransferFunction> (other);
+ auto o = dynamic_pointer_cast<const ModifiedGammaTransferFunction>(other);
if (!o) {
return false;
}
return (
- fabs (_power - o->_power) < epsilon &&
- fabs (_threshold - o->_threshold) < epsilon &&
- fabs (_A - o->_A) < epsilon &&
- fabs (_B - o->_B) < epsilon
+ fabs(_power - o->_power) < epsilon &&
+ fabs(_threshold - o->_threshold) < epsilon &&
+ fabs(_A - o->_A) < epsilon &&
+ fabs(_B - o->_B) < epsilon
);
}
/*
- Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2021 Carl Hetherington <cth@carlh.net>
This file is part of libdcp.
files in the program, then also delete it here.
*/
+
/** @file src/modified_gamma_transfer_function.h
- * @brief ModifiedGammaTransferFunction class.
+ * @brief ModifiedGammaTransferFunction class
*/
+
#include "transfer_function.h"
+
namespace dcp {
+
/** A transfer function which for an input x gives a linear output y where
*
* y = x / B for x <= threshold
double _B;
};
+
}
files in the program, then also delete it here.
*/
+
+/** @file src/mono_picture_asset.cc
+ * @brief MonoPictureAsset class
+ */
+
+
#include "mono_picture_asset.h"
#include "mono_picture_asset_writer.h"
#include "mono_picture_asset_reader.h"
#include <asdcp/AS_DCP.h>
#include <asdcp/KM_fileio.h>
+
using std::string;
using std::vector;
using std::list;
#endif
using namespace dcp;
+
MonoPictureAsset::MonoPictureAsset (boost::filesystem::path file)
: PictureAsset (file)
{
_id = read_writer_info (info);
}
+
MonoPictureAsset::MonoPictureAsset (Fraction edit_rate, Standard standard)
: PictureAsset (edit_rate, standard)
{
}
+
static void
storing_note_handler (list<pair<NoteType, string> >& notes, NoteType t, string s)
{
notes.push_back (make_pair (t, s));
}
+
bool
MonoPictureAsset::equals (shared_ptr<const Asset> other, EqualityOptions opt, NoteHandler note) const
{
return result;
}
+
shared_ptr<PictureAssetWriter>
MonoPictureAsset::start_write (boost::filesystem::path file, bool overwrite)
{
- return make_shared<MonoPictureAssetWriter>(this, file, overwrite);
+ /* Can't use make_shared here as the MonoPictureAssetWriter constructor is private */
+ return shared_ptr<MonoPictureAssetWriter>(new MonoPictureAssetWriter(this, file, overwrite));
}
shared_ptr<MonoPictureAssetReader>
MonoPictureAsset::start_read () const
{
- return make_shared<MonoPictureAssetReader>(this, key(), standard());
+ /* Can't use make_shared here as the MonoPictureAssetReader constructor is private */
+ return shared_ptr<MonoPictureAssetReader>(new MonoPictureAssetReader(this, key(), standard()));
+
}
string
files in the program, then also delete it here.
*/
+
+/** @file src/mono_picture_asset.cc
+ * @brief MonoPictureAsset class
+ */
+
+
#ifndef LIBDCP_MONO_PICTURE_ASSET_H
#define LIBDCP_MONO_PICTURE_ASSET_H
+
#include "picture_asset.h"
#include "mono_picture_asset_reader.h"
+
namespace dcp {
+
class MonoPictureAssetWriter;
+
/** @class MonoPictureAsset
- * @brief A 2D (monoscopic) picture asset.
+ * @brief A 2D (monoscopic) picture asset
*/
class MonoPictureAsset : public PictureAsset
{
/*
- Copyright (C) 2016 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2016-2021 Carl Hetherington <cth@carlh.net>
This file is part of libdcp.
files in the program, then also delete it here.
*/
+
+/** @file src/mono_picture_asset_reader.h
+ * @brief MonoPictureAssetReader typedef
+ */
+
+
#ifndef LIBDCP_MONO_PICTURE_ASSET_READER_H
#define LIBDCP_MONO_PICTURE_ASSET_READER_H
+
#include "asset_reader.h"
#include "mono_picture_frame.h"
+
namespace dcp {
+
typedef AssetReader<ASDCP::JP2K::MXFReader, MonoPictureFrame> MonoPictureAssetReader;
+
}
+
#endif
/*
- Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2021 Carl Hetherington <cth@carlh.net>
This file is part of libdcp.
files in the program, then also delete it here.
*/
+
/** @file src/mono_picture_asset_writer.cc
* @brief MonoPictureAssetWriter class
*/
+
#include "mono_picture_asset_writer.h"
#include "exceptions.h"
#include "picture_asset.h"
#include <asdcp/AS_DCP.h>
#include <asdcp/KM_fileio.h>
+
#include "picture_asset_writer_common.cc"
+
using std::string;
using std::shared_ptr;
using namespace dcp;
+
struct MonoPictureAssetWriter::ASDCPState : public ASDCPStateBase
{
ASDCP::JP2K::MXFWriter mxf_writer;
};
+
/** @param a Asset to write to. `a' must not be deleted while
* this writer class still exists, or bad things will happen.
*/
}
+
void
MonoPictureAssetWriter::start (uint8_t const * data, int size)
{
_picture_asset->set_frame_rate (_picture_asset->edit_rate());
}
+
FrameInfo
MonoPictureAssetWriter::write (uint8_t const * data, int size)
{
start (data, size);
}
- if (ASDCP_FAILURE (_state->j2k_parser.OpenReadFrame (data, size, _state->frame_buffer))) {
+ if (ASDCP_FAILURE (_state->j2k_parser.OpenReadFrame(data, size, _state->frame_buffer))) {
boost::throw_exception (MiscError ("could not parse J2K frame"));
}
uint64_t const before_offset = _state->mxf_writer.Tell ();
string hash;
- ASDCP::Result_t const r = _state->mxf_writer.WriteFrame (_state->frame_buffer, _crypto_context->context(), _crypto_context->hmac(), &hash);
- if (ASDCP_FAILURE (r)) {
+ auto const r = _state->mxf_writer.WriteFrame (_state->frame_buffer, _crypto_context->context(), _crypto_context->hmac(), &hash);
+ if (ASDCP_FAILURE(r)) {
boost::throw_exception (MXFFileError ("error in writing video MXF", _file.string(), r));
}
return FrameInfo (before_offset, _state->mxf_writer.Tell() - before_offset, hash);
}
+
void
MonoPictureAssetWriter::fake_write (int size)
{
DCP_ASSERT (_started);
DCP_ASSERT (!_finalized);
- Kumu::Result_t r = _state->mxf_writer.FakeWriteFrame (size);
- if (ASDCP_FAILURE (r)) {
- boost::throw_exception (MXFFileError ("error in writing video MXF", _file.string(), r));
+ auto r = _state->mxf_writer.FakeWriteFrame (size);
+ if (ASDCP_FAILURE(r)) {
+ boost::throw_exception (MXFFileError("error in writing video MXF", _file.string(), r));
}
++_frames_written;
}
+
bool
MonoPictureAssetWriter::finalize ()
{
if (_started) {
- Kumu::Result_t r = _state->mxf_writer.Finalize();
- if (ASDCP_FAILURE (r)) {
- boost::throw_exception (MXFFileError ("error in finalizing video MXF", _file.string(), r));
+ auto r = _state->mxf_writer.Finalize();
+ if (ASDCP_FAILURE(r)) {
+ boost::throw_exception (MXFFileError("error in finalizing video MXF", _file.string(), r));
}
}
/*
- Copyright (C) 2012-2015 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2021 Carl Hetherington <cth@carlh.net>
This file is part of libdcp.
files in the program, then also delete it here.
*/
+
/** @file src/mono_picture_asset_writer.h
* @brief MonoPictureAssetWriter class
*/
+
#ifndef LIBDCP_MONO_PICTURE_ASSET_WRITER_H
#define LIBDCP_MONO_PICTURE_ASSET_WRITER_H
+
#include "picture_asset_writer.h"
#include <memory>
#include <boost/utility.hpp>
#include <stdint.h>
#include <string>
+
namespace dcp {
+
/** @class MonoPictureAssetWriter
* @brief A helper class for writing to MonoPictureAssets
*
class MonoPictureAssetWriter : public PictureAssetWriter
{
public:
- MonoPictureAssetWriter (PictureAsset *, boost::filesystem::path file, bool);
-
FrameInfo write (uint8_t const *, int);
void fake_write (int size);
bool finalize ();
private:
friend class MonoPictureAsset;
+ MonoPictureAssetWriter (PictureAsset* a, boost::filesystem::path file, bool);
+
void start (uint8_t const *, int);
/* do this with an opaque pointer so we don't have to include
std::shared_ptr<ASDCPState> _state;
};
+
}
+
#endif
/*
- Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2021 Carl Hetherington <cth@carlh.net>
This file is part of libdcp.
files in the program, then also delete it here.
*/
+
/** @file src/mono_picture_frame.cc
- * @brief MonoPictureFrame class.
+ * @brief MonoPictureFrame class
*/
+
#include "mono_picture_frame.h"
#include "exceptions.h"
#include "util.h"
#include <asdcp/KM_fileio.h>
#include <asdcp/AS_DCP.h>
+
+using std::make_shared;
using std::string;
using std::shared_ptr;
using boost::optional;
using namespace dcp;
-/** Make a picture frame from a JPEG2000 file.
- * @param path Path to JPEG2000 file.
- */
+
MonoPictureFrame::MonoPictureFrame (boost::filesystem::path path)
{
- boost::uintmax_t const size = boost::filesystem::file_size (path);
+ auto const size = boost::filesystem::file_size (path);
_buffer.reset(new ASDCP::JP2K::FrameBuffer(size));
- FILE* f = fopen_boost (path, "rb");
+ auto f = fopen_boost (path, "rb");
if (!f) {
- boost::throw_exception (FileError ("could not open JPEG2000 file", path, errno));
+ boost::throw_exception (FileError("could not open JPEG2000 file", path, errno));
}
size_t n = fread (data(), 1, size, f);
+ fclose (f);
+
if (n != size) {
- boost::throw_exception (FileError ("could not read from JPEG2000 file", path, errno));
+ boost::throw_exception (FileError("could not read from JPEG2000 file", path, errno));
}
- fclose (f);
-
_buffer->Size (size);
}
+
/** Make a picture frame from a 2D (monoscopic) asset.
* @param reader Reader for the asset's MXF file.
* @param n Frame within the asset, not taking EntryPoint into account.
MonoPictureFrame::MonoPictureFrame (ASDCP::JP2K::MXFReader* reader, int n, shared_ptr<DecryptionContext> c)
{
/* XXX: unfortunate guesswork on this buffer size */
- _buffer.reset(new ASDCP::JP2K::FrameBuffer(4 * Kumu::Megabyte));
+ _buffer = make_shared<ASDCP::JP2K::FrameBuffer>(4 * Kumu::Megabyte);
- ASDCP::Result_t const r = reader->ReadFrame (n, *_buffer, c->context(), c->hmac());
+ auto const r = reader->ReadFrame (n, *_buffer, c->context(), c->hmac());
- if (ASDCP_FAILURE (r)) {
- boost::throw_exception (ReadError (String::compose ("could not read video frame %1 (%2)", n, static_cast<int>(r))));
+ if (ASDCP_FAILURE(r)) {
+ boost::throw_exception (ReadError(String::compose ("could not read video frame %1 (%2)", n, static_cast<int>(r))));
}
}
+
MonoPictureFrame::MonoPictureFrame (uint8_t const * data, int size)
{
- _buffer.reset(new ASDCP::JP2K::FrameBuffer(size));
+ _buffer = make_shared<ASDCP::JP2K::FrameBuffer>(size);
_buffer->Size (size);
memcpy (_buffer->Data(), data, size);
}
-/** @return Pointer to JPEG2000 data */
uint8_t const *
MonoPictureFrame::data () const
{
return _buffer->RoData ();
}
-/** @return Pointer to JPEG2000 data */
+
uint8_t *
MonoPictureFrame::data ()
{
return _buffer->Data ();
}
-/** @return Size of JPEG2000 data in bytes */
+
int
MonoPictureFrame::size () const
{
return _buffer->Size ();
}
-/** @param reduce a factor by which to reduce the resolution
- * of the image, expressed as a power of two (pass 0 for no
- * reduction).
- */
+
shared_ptr<OpenJPEGImage>
MonoPictureFrame::xyz_image (int reduce) const
{
- return decompress_j2k (const_cast<uint8_t*> (_buffer->RoData()), _buffer->Size(), reduce);
+ return decompress_j2k (const_cast<uint8_t*>(_buffer->RoData()), _buffer->Size(), reduce);
}
*/
-#ifndef LIBDCP_MONO_PICTURE_FRAME_H
-#define LIBDCP_MONO_PICTURE_FRAME_H
-
-
/** @file src/mono_picture_frame.h
* @brief MonoPictureFrame class
*/
-#include "types.h"
+#ifndef LIBDCP_MONO_PICTURE_FRAME_H
+#define LIBDCP_MONO_PICTURE_FRAME_H
+
+
#include "asset_reader.h"
-#include <memory>
+#include "types.h"
#include <boost/filesystem.hpp>
#include <boost/optional.hpp>
-#include <string>
+#include <memory>
#include <stdint.h>
+#include <string>
namespace ASDCP {
/** @class MonoPictureFrame
- * @brief A single frame of a 2D (monoscopic) picture asset.
+ * @brief A single frame of a 2D (monoscopic) picture asset
*/
class MonoPictureFrame : public Data
{
public:
+ /** Make a picture frame from a JPEG2000 file.
+ * @param path Path to JPEG2000 file.
+ */
explicit MonoPictureFrame (boost::filesystem::path path);
MonoPictureFrame (uint8_t const * data, int size);
MonoPictureFrame (MonoPictureFrame const&) = delete;
MonoPictureFrame& operator= (MonoPictureFrame const&) = delete;
+ /** @param reduce a factor by which to reduce the resolution
+ * of the image, expressed as a power of two (pass 0 for no
+ * reduction).
+ */
std::shared_ptr<OpenJPEGImage> xyz_image (int reduce = 0) const;
+ /** @return Pointer to JPEG2000 data */
uint8_t const * data () const;
+
+ /** @return Pointer to JPEG2000 data */
uint8_t* data ();
+
+ /** @return Size of JPEG2000 data in bytes */
int size () const;
private:
/*
- Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2021 Carl Hetherington <cth@carlh.net>
This file is part of libdcp.
files in the program, then also delete it here.
*/
-/** @file src/asset.cc
- * @brief Parent class for assets of DCPs made up of MXF files.
+
+/** @file src/mxf.cc
+ * @brief MXF class
*/
+
#include "raw_convert.h"
#include "mxf.h"
#include "util.h"
#include <boost/filesystem.hpp>
#include <iostream>
+
using std::string;
using std::cout;
using std::list;
using std::dynamic_pointer_cast;
using namespace dcp;
+
MXF::MXF ()
: _context_id (make_uuid ())
{
*/
}
+
MXF::MXF (Standard standard)
: _context_id (make_uuid ())
, _standard (standard)
}
+
void
MXF::fill_writer_info (ASDCP::WriterInfo* writer_info, string id) const
{
}
}
-/** Set the (private) key that will be used to encrypt or decrypt this MXF's content.
- * This is the top-secret key that is distributed (itself encrypted) to cinemas
- * via Key Delivery Messages (KDMs).
- * @param key Key to use.
- */
+
void
MXF::set_key (Key key)
{
}
}
+
string
MXF::read_writer_info (ASDCP::WriterInfo const & info)
{
/*
- Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2021 Carl Hetherington <cth@carlh.net>
This file is part of libdcp.
files in the program, then also delete it here.
*/
+
+/** @file src/mxf.h
+ * @brief MXF class
+ */
+
+
#ifndef LIBDCP_MXF_H
#define LIBDCP_MXF_H
+
#include "asset.h"
#include "key.h"
#include "metadata.h"
#include "dcp_assert.h"
-
#include <boost/signals2.hpp>
+
namespace ASDCP {
class AESDecContext;
struct WriterInfo;
}
+
/* Undefine some stuff that the OS X 10.5 SDK defines */
#undef Key
#undef set_key
+
namespace dcp
{
+
class MXFMetadata;
class PictureAssetWriter;
+
/** @class MXF
- * @brief Parent for classes which represent MXF files.
+ * @brief Parent for classes which represent MXF files
*/
class MXF
{
return _key_id;
}
+ /** Set the (private) key that will be used to encrypt or decrypt this MXF's content
+ * This is the top-secret key that is distributed (itself encrypted) to cinemas
+ * via Key Delivery Messages (KDMs)
+ * @param key Key to use
+ */
virtual void set_key (Key);
/** @return encryption/decryption key, if one has been set */
boost::optional<Standard> _standard;
};
+
}
+
#endif
/*
- Copyright (C) 2016 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2016-2021 Carl Hetherington <cth@carlh.net>
This file is part of libdcp.
files in the program, then also delete it here.
*/
+
+/** @file src/name_format.cc
+ * @brief NameFormat class
+ */
+
+
#include "name_format.h"
#include <boost/optional.hpp>
+
using std::string;
using std::map;
using boost::optional;
using namespace dcp;
+
static char
filter (char c)
{
return c;
}
+
static string
filter (string c)
{
}
-/** @param values Values to replace our specifications with; e.g.
- * if the specification contains %c it will be be replaced with the
- * value corresponding to the key 'c'.
- * @param suffix Suffix to add on after processing the specification.
- * @param ignore Any specification characters in this string will not
- * be replaced, but left as-is.
- */
string
NameFormat::get (Map values, string suffix, string ignore) const
{
bool done = false;
if (_specification[i] == '%' && (i < _specification.length() - 1)) {
char const key = _specification[i + 1];
- Map::const_iterator j = values.find(key);
+ auto j = values.find(key);
if (j != values.end() && ignore.find(key) == string::npos) {
result += filter (j->second);
++i;
return result + suffix;
}
+
bool
dcp::operator== (NameFormat const & a, NameFormat const & b)
{
/*
- Copyright (C) 2016 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2016-2021 Carl Hetherington <cth@carlh.net>
This file is part of libdcp.
files in the program, then also delete it here.
*/
+
+/** @file src/name_format.h
+ * @brief NameFormat class
+ */
+
+
#ifndef LIBDCP_NAME_FORMAT
#define LIBDCP_NAME_FORMAT
+
#include <string>
#include <boost/optional.hpp>
#include <map>
#include <list>
+
namespace dcp {
+
class NameFormat
{
public:
typedef std::map<char, std::string> Map;
+ /** @param values Values to replace our specifications with; e.g.
+ * if the specification contains %c it will be be replaced with the
+ * value corresponding to the key 'c'.
+ * @param suffix Suffix to add on after processing the specification.
+ * @param ignore Any specification characters in this string will not
+ * be replaced, but left as-is.
+ */
std::string get (Map, std::string suffix, std::string ignore = "") const;
private:
std::string _specification;
};
+
extern bool operator== (NameFormat const & a, NameFormat const & b);
+
}
+
#endif
/*
- Copyright (C) 2012-2015 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2021 Carl Hetherington <cth@carlh.net>
This file is part of libdcp.
files in the program, then also delete it here.
*/
+
/** @file src/openjpeg_image.cc
* @brief OpenJPEGImage class.
*/
+
#include "openjpeg_image.h"
#include "dcp_assert.h"
#include <openjpeg.h>
#include <stdexcept>
+
using namespace dcp;
+
#ifdef LIBDCP_OPENJPEG1
#define OPJ_CLRSPC_SRGB CLRSPC_SRGB
#endif
-/** Construct an OpenJPEGImage, taking ownership of the opj_image_t */
+
OpenJPEGImage::OpenJPEGImage (opj_image_t* image)
: _opj_image (image)
{
DCP_ASSERT (_opj_image->numcomps == 3);
}
+
#ifdef LIBDCP_OPENJPEG1
typedef int32_t OPJ_INT32;
typedef uint8_t OPJ_BYTE;
#endif
+
OpenJPEGImage::OpenJPEGImage (OpenJPEGImage const & other)
{
- _opj_image = reinterpret_cast<opj_image_t*> (malloc (sizeof (opj_image_t)));
+ _opj_image = reinterpret_cast<opj_image_t*>(malloc(sizeof(opj_image_t)));
DCP_ASSERT (_opj_image);
memcpy (_opj_image, other._opj_image, sizeof (opj_image_t));
memcpy (_opj_image->icc_profile_buf, other._opj_image->icc_profile_buf, _opj_image->icc_profile_len);
}
-/** Construct a new OpenJPEGImage with undefined contents.
- * @param size Size for the frame in pixels.
- */
+
OpenJPEGImage::OpenJPEGImage (Size size)
{
create (size);
}
-/** @param data_16 XYZ/RGB image data in packed 16:16:16, 48bpp with
- * the 2-byte value for each component stored as little-endian.
- */
+
OpenJPEGImage::OpenJPEGImage (uint8_t const * data_16, dcp::Size size, int stride)
{
create (size);
}
}
+
void
OpenJPEGImage::create (Size size)
{
_opj_image->y1 = size.height;
}
-/** OpenJPEGImage destructor */
+
OpenJPEGImage::~OpenJPEGImage ()
{
opj_image_destroy (_opj_image);
}
-/** @param c Component index (0, 1 or 2)
- * @return Pointer to the data for component c.
- */
+
int *
OpenJPEGImage::data (int c) const
{
return _opj_image->comps[c].data;
}
-/** @return Size of the image in pixels */
+
dcp::Size
OpenJPEGImage::size () const
{
return dcp::Size (_opj_image->x1, _opj_image->y1);
}
+
int
OpenJPEGImage::precision (int component) const
{
return _opj_image->comps[component].prec;
}
+
int
OpenJPEGImage::factor (int component) const
{
return _opj_image->comps[component].factor;
}
+
bool
OpenJPEGImage::srgb () const
{
/*
- Copyright (C) 2012-2015 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2021 Carl Hetherington <cth@carlh.net>
This file is part of libdcp.
files in the program, then also delete it here.
*/
+
/** @file src/openjpeg_image.h
- * @brief OpenJPEGImage class.
+ * @brief OpenJPEGImage class
*/
+
#include "util.h"
+
struct opj_image;
typedef struct opj_image opj_image_t;
+
namespace dcp {
+
/** @class OpenJPEGImage
- * @brief A wrapper of libopenjpeg's opj_image_t.
+ * @brief A wrapper of libopenjpeg's opj_image_t
*/
class OpenJPEGImage
{
public:
+ /** Construct an OpenJPEGImage, taking ownership of the opj_image_t */
explicit OpenJPEGImage (opj_image_t *);
+
explicit OpenJPEGImage (OpenJPEGImage const & other);
+
+ /** Construct a new OpenJPEGImage with undefined contents
+ * @param size Size for the frame in pixels
+ */
explicit OpenJPEGImage (Size);
+
+ /** @param data_16 XYZ/RGB image data in packed 16:16:16, 48bpp with
+ * the 2-byte value for each component stored as little-endian
+ */
OpenJPEGImage (uint8_t const * in_16, dcp::Size size, int stride);
+
~OpenJPEGImage ();
+ /** @param c Component index (0, 1 or 2)
+ * @return Pointer to the data for component c.
+ */
int* data (int) const;
+
+ /** @return Size of the image in pixels */
Size size () const;
+
int precision (int component) const;
bool srgb () const;
int factor (int component) const;
private:
void create (Size size);
- opj_image_t* _opj_image; ///< opj_image_t that we are managing
+ opj_image_t* _opj_image = nullptr; ///< opj_image_t that we are managing
};
+
}
/*
- Copyright (C) 2012-2015 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2021 Carl Hetherington <cth@carlh.net>
This file is part of libdcp.
files in the program, then also delete it here.
*/
+
+/** @file src/picture_asset.cc
+ * @brief PictureAsset class
+ */
+
+
#include "picture_asset.h"
#include "util.h"
#include "exceptions.h"
#include <list>
#include <stdexcept>
+
using std::string;
using std::list;
using std::vector;
using std::shared_ptr;
using namespace dcp;
-/** Load a PictureAsset from a file */
+
PictureAsset::PictureAsset (boost::filesystem::path file)
: Asset (file)
, _intrinsic_duration (0)
}
-/** Create a new PictureAsset with a given edit rate and standard */
+
PictureAsset::PictureAsset (Fraction edit_rate, Standard standard)
: MXF (standard)
, _edit_rate (edit_rate)
}
+
void
PictureAsset::read_picture_descriptor (ASDCP::JP2K::PictureDescriptor const & desc)
{
_screen_aspect_ratio = Fraction (desc.AspectRatio.Numerator, desc.AspectRatio.Denominator);
}
+
bool
PictureAsset::descriptor_equals (
ASDCP::JP2K::PictureDescriptor const & a, ASDCP::JP2K::PictureDescriptor const & b, NoteHandler note
return true;
}
+
bool
PictureAsset::frame_buffer_equals (
int frame, EqualityOptions opt, NoteHandler note,
}
/* Decompress the images to bitmaps */
- shared_ptr<OpenJPEGImage> image_A = decompress_j2k (const_cast<uint8_t*> (data_A), size_A, 0);
- shared_ptr<OpenJPEGImage> image_B = decompress_j2k (const_cast<uint8_t*> (data_B), size_B, 0);
+ auto image_A = decompress_j2k (const_cast<uint8_t*>(data_A), size_A, 0);
+ auto image_B = decompress_j2k (const_cast<uint8_t*>(data_B), size_B, 0);
/* Compare them */
double const mean = double (total) / abs_diffs.size ();
uint64_t total_squared_deviation = 0;
- for (vector<int>::iterator j = abs_diffs.begin(); j != abs_diffs.end(); ++j) {
- total_squared_deviation += pow (*j - mean, 2);
+ for (auto j: abs_diffs) {
+ total_squared_deviation += pow (j - mean, 2);
}
- double const std_dev = sqrt (double (total_squared_deviation) / abs_diffs.size());
+ auto const std_dev = sqrt (double (total_squared_deviation) / abs_diffs.size());
note (NoteType::NOTE, String::compose("mean difference %1 deviation %2", mean, std_dev));
return true;
}
+
string
PictureAsset::static_pkl_type (Standard standard)
{
}
}
+
string
PictureAsset::pkl_type (Standard standard) const
{
/*
- Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2021 Carl Hetherington <cth@carlh.net>
This file is part of libdcp.
files in the program, then also delete it here.
*/
-#ifndef LIBDCP_PICTURE_ASSET_H
-#define LIBDCP_PICTURE_ASSET_H
/** @file src/picture_asset.h
- * @brief PictureAsset class.
+ * @brief PictureAsset class
*/
+
+#ifndef LIBDCP_PICTURE_ASSET_H
+#define LIBDCP_PICTURE_ASSET_H
+
+
#include "mxf.h"
#include "util.h"
#include "metadata.h"
+
namespace ASDCP {
namespace JP2K {
struct PictureDescriptor;
}
}
-namespace dcp
-{
+
+namespace dcp {
+
class MonoPictureFrame;
class StereoPictureFrame;
class PictureAssetWriter;
+
/** @class PictureAsset
- * @brief An asset made up of JPEG2000 data.
+ * @brief An asset made up of JPEG2000 data
*/
class PictureAsset : public Asset, public MXF
{
public:
+ /** Load a PictureAsset from a file */
explicit PictureAsset (boost::filesystem::path file);
+
+ /** Create a new PictureAsset with a given edit rate and standard */
explicit PictureAsset (Fraction edit_rate, Standard standard);
virtual std::shared_ptr<PictureAssetWriter> start_write (
/** The total length of this content in video frames. The amount of
* content presented may be less than this.
*/
- int64_t _intrinsic_duration;
+ int64_t _intrinsic_duration = 0;
/** picture size in pixels */
Size _size;
Fraction _frame_rate;
}
+
#endif
/*
- Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2021 Carl Hetherington <cth@carlh.net>
This file is part of libdcp.
files in the program, then also delete it here.
*/
+
+/** @file src/picture_asset_writer.cc
+ * @brief PictureAssetWriter and FrameInfo classes
+ */
+
+
#include "picture_asset_writer.h"
#include "exceptions.h"
#include "picture_asset.h"
#include <inttypes.h>
#include <stdint.h>
+
using std::string;
using std::shared_ptr;
using namespace dcp;
+
PictureAssetWriter::PictureAssetWriter (PictureAsset* asset, boost::filesystem::path file, bool overwrite)
: AssetWriter (asset, file)
, _picture_asset (asset)
/*
- Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2021 Carl Hetherington <cth@carlh.net>
This file is part of libdcp.
files in the program, then also delete it here.
*/
+
/** @file src/picture_asset_writer.h
* @brief PictureAssetWriter and FrameInfo classes.
*/
+
#ifndef LIBDCP_PICTURE_ASSET_WRITER_H
#define LIBDCP_PICTURE_ASSET_WRITER_H
+
#include "metadata.h"
#include "types.h"
#include "asset_writer.h"
#include <stdint.h>
#include <string>
+
namespace dcp {
+
class PictureAsset;
+
/** @class FrameInfo
* @brief Information about a single frame (either a monoscopic frame or a left *or* right eye stereoscopic frame)
*/
struct FrameInfo
{
- FrameInfo ()
- : offset (0)
- , size (0)
- {}
+ FrameInfo () {}
FrameInfo (uint64_t o, uint64_t s, std::string h)
: offset (o)
, hash (h)
{}
- uint64_t offset;
- uint64_t size;
+ uint64_t offset = 0;
+ uint64_t size = 0;
std::string hash;
};
+
/** @class PictureAssetWriter
* @brief Parent class for classes which write picture assets.
*/
PictureAssetWriter (PictureAsset *, boost::filesystem::path, bool);
PictureAsset* _picture_asset;
- bool _overwrite;
+ bool _overwrite = false;
};
+
}
+
#endif
/*
- Copyright (C) 2012-2015 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2021 Carl Hetherington <cth@carlh.net>
This file is part of libdcp.
files in the program, then also delete it here.
*/
+
+/** @file src/picture_asset_writer_common.cc
+ * @brief Common parts of PictureAssetWriter
+ */
+
+
using std::shared_ptr;
+
namespace dcp {
+
struct ASDCPStateBase
{
ASDCPStateBase ()
ASDCP::JP2K::PictureDescriptor picture_descriptor;
};
+
}
+
template <class P, class Q>
void dcp::start (PictureAssetWriter* writer, shared_ptr<P> state, Q* asset, uint8_t const * data, int size)
{
asset->set_file (writer->_file);
- if (ASDCP_FAILURE (state->j2k_parser.OpenReadFrame (data, size, state->frame_buffer))) {
+ if (ASDCP_FAILURE (state->j2k_parser.OpenReadFrame(data, size, state->frame_buffer))) {
boost::throw_exception (MiscError ("could not parse J2K frame"));
}
asset->fill_writer_info (&state->writer_info, asset->id());
- Kumu::Result_t r = state->mxf_writer.OpenWrite (
+ auto r = state->mxf_writer.OpenWrite (
asset->file()->string().c_str(),
state->writer_info,
state->picture_descriptor,
writer->_overwrite
);
- if (ASDCP_FAILURE (r)) {
- boost::throw_exception (MXFFileError ("could not open MXF file for writing", asset->file()->string(), r));
+ if (ASDCP_FAILURE(r)) {
+ boost::throw_exception (MXFFileError("could not open MXF file for writing", asset->file()->string(), r));
}
writer->_started = true;
*/
+/** @file src/pkl.cc
+ * @brief PKL class
+ */
+
+
#include "pkl.h"
#include "exceptions.h"
#include "util.h"
*/
+/** @file src/pkl.cc
+ * @brief PKL class
+ */
+
+
#ifndef LIBDCP_PKL_H
#define LIBDCP_PKL_H
mutable boost::optional<boost::filesystem::path> _file;
};
+
}
+
#endif
/*
- Copyright (C) 2014-2016 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2014-2021 Carl Hetherington <cth@carlh.net>
This file is part of libdcp.
files in the program, then also delete it here.
*/
+
#include "raw_convert.h"
#include "locale_convert.h"
#include <boost/algorithm/string.hpp>
+
using std::string;
using std::wstring;
+
/** @param v Numeric value as an ASCII string */
static
string
return v;
}
+
static
string
make_local (string v)
return v;
}
+
template <>
string
dcp::raw_convert (unsigned char v, int precision, bool fixed)
return make_raw (locale_convert<string> (v, precision, fixed));
}
+
template <>
string
dcp::raw_convert (unsigned short int v, int precision, bool fixed)
return make_raw (locale_convert<string> (v, precision, fixed));
}
+
template <>
string
dcp::raw_convert (int v, int precision, bool fixed)
return make_raw (locale_convert<string> (v, precision, fixed));
}
+
template <>
string
dcp::raw_convert (unsigned int v, int precision, bool fixed)
return make_raw (locale_convert<string> (v, precision, fixed));
}
+
template <>
string
dcp::raw_convert (long v, int precision, bool fixed)
return make_raw (locale_convert<string> (v, precision, fixed));
}
+
template <>
string
dcp::raw_convert (unsigned long v, int precision, bool fixed)
return make_raw (locale_convert<string> (v, precision, fixed));
}
+
template <>
string
dcp::raw_convert (long long v, int precision, bool fixed)
return make_raw (locale_convert<string> (v, precision, fixed));
}
+
template <>
string
dcp::raw_convert (unsigned long long v, int precision, bool fixed)
return make_raw (locale_convert<string> (v, precision, fixed));
}
+
template <>
string
dcp::raw_convert (float v, int precision, bool fixed)
return make_raw (locale_convert<string> (v, precision, fixed));
}
+
template <>
string
dcp::raw_convert (double v, int precision, bool fixed)
return make_raw (locale_convert<string> (v, precision, fixed));
}
+
template <>
string
dcp::raw_convert (char const * v, int, bool)
return v;
}
+
template <>
string
dcp::raw_convert (char* v, int, bool)
return v;
}
+
template <>
string
dcp::raw_convert (string v, int, bool)
return v;
}
+
template <>
string
dcp::raw_convert (char v, int, bool)
return s;
}
+
template <>
string
dcp::raw_convert (wchar_t const * v, int, bool)
return string (w.begin(), w.end());
}
+
template <>
unsigned char
dcp::raw_convert (std::string v, int precision, bool fixed)
return locale_convert<unsigned char> (make_local (v), precision, fixed);
}
+
template <>
unsigned short int
dcp::raw_convert (std::string v, int precision, bool fixed)
return locale_convert<unsigned short int> (make_local (v), precision, fixed);
}
+
template <>
int
dcp::raw_convert (string v, int precision, bool fixed)
return locale_convert<int> (make_local (v), precision, fixed);
}
+
template <>
long
dcp::raw_convert (string v, int precision, bool fixed)
return locale_convert<long> (make_local (v), precision, fixed);
}
+
template <>
unsigned long
dcp::raw_convert (string v, int precision, bool fixed)
return locale_convert<unsigned long> (make_local (v), precision, fixed);
}
+
template <>
long long
dcp::raw_convert (string v, int precision, bool fixed)
return locale_convert<long long> (make_local (v), precision, fixed);
}
+
template <>
unsigned long long
dcp::raw_convert (string v, int precision, bool fixed)
return locale_convert<unsigned long long> (make_local (v), precision, fixed);
}
+
template <>
int
dcp::raw_convert (char const * v, int precision, bool fixed)
return locale_convert<int> (make_local (v), precision, fixed);
}
+
template <>
float
dcp::raw_convert (string v, int precision, bool fixed)
return locale_convert<float> (make_local (v), precision, fixed);
}
+
template <>
float
dcp::raw_convert (char const * v, int precision, bool fixed)
return locale_convert<float> (make_local (v), precision, fixed);
}
+
template <>
double
dcp::raw_convert (string v, int precision, bool fixed)
return locale_convert<double> (make_local (v), precision, fixed);
}
+
template <>
double
dcp::raw_convert (char const * v, int precision, bool fixed)
/*
- Copyright (C) 2014 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2014-2021 Carl Hetherington <cth@carlh.net>
This file is part of libdcp.
files in the program, then also delete it here.
*/
+
+/** @file src/raw_convert.h
+ * @brief Methods for conversion to/from string
+ */
+
+
#ifndef LIBDCP_RAW_CONVERT_H
#define LIBDCP_RAW_CONVERT_H
+
#include "util.h"
#include <boost/static_assert.hpp>
#include <iomanip>
+
namespace dcp {
+
/** A sort-of version of boost::lexical_cast that does uses the "C"
* locale (i.e. no thousands separators and a . for the decimal separator).
*/
double
raw_convert (char const * v, int, bool);
+
}
+
#endif
*/
+/** @file src/reel.cc
+ * @brief Reel class
+ */
+
+
#include "reel.h"
#include "util.h"
#include "picture_asset.h"
*/
+/** @file src/reel.cc
+ * @brief Reel class
+ */
+
+
#ifndef LIBDCP_REEL_H
#define LIBDCP_REEL_H
/*
- Copyright (C) 2014-2015 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2014-2021 Carl Hetherington <cth@carlh.net>
This file is part of libdcp.
files in the program, then also delete it here.
*/
+
/** @file src/reel_asset.cc
- * @brief ReelAsset class.
+ * @brief ReelAsset class
*/
+
#include "raw_convert.h"
#include "reel_asset.h"
#include "asset.h"
#include <libcxml/cxml.h>
#include <libxml++/libxml++.h>
+
using std::pair;
using std::string;
using std::make_pair;
using boost::optional;
using namespace dcp;
-/** Construct a ReelAsset.
- * @param id ID of this ReelAsset (which is that of the MXF, if there is one)
- * @param edit_rate Edit rate for the asset.
- * @param intrinsic_duration Intrinsic duration of this asset.
- * @param entry_point Entry point to use in that asset.
- */
+
ReelAsset::ReelAsset (string id, Fraction edit_rate, int64_t intrinsic_duration, int64_t entry_point)
: Object (id)
, _intrinsic_duration (intrinsic_duration)
DCP_ASSERT (_entry_point <= _intrinsic_duration);
}
+
ReelAsset::ReelAsset (shared_ptr<const cxml::Node> node)
: Object (remove_urn_uuid (node->string_child ("Id")))
, _intrinsic_duration (node->number_child<int64_t> ("IntrinsicDuration"))
}
+
xmlpp::Node*
ReelAsset::write_to_cpl_asset (xmlpp::Node* node, Standard standard, optional<string> hash) const
{
- xmlpp::Element* a = node->add_child (cpl_node_name (standard));
- pair<string, string> const attr = cpl_node_attribute (standard);
+ auto a = node->add_child (cpl_node_name (standard));
+ auto const attr = cpl_node_attribute (standard);
if (!attr.first.empty ()) {
a->set_attribute (attr.first, attr.second);
}
- pair<string, string> const ns = cpl_node_namespace (standard);
+ auto const ns = cpl_node_namespace (standard);
if (!ns.first.empty ()) {
a->set_namespace_declaration (ns.first, ns.second);
}
return a;
}
+
pair<string, string>
ReelAsset::cpl_node_attribute (Standard) const
{
return make_pair ("", "");
}
+
pair<string, string>
ReelAsset::cpl_node_namespace (Standard) const
{
return make_pair ("", "");
}
+
bool
ReelAsset::asset_equals (shared_ptr<const ReelAsset> other, EqualityOptions opt, NoteHandler note) const
{
return true;
}
-/** @return <Duration>, or <IntrinsicDuration> - <EntryPoint> if <Duration> is not present */
+
int64_t
ReelAsset::actual_duration () const
{
files in the program, then also delete it here.
*/
+
/** @file src/reel_asset.h
- * @brief ReelAsset class.
+ * @brief ReelAsset class
*/
+
#ifndef LIBDCP_REEL_ASSET_H
#define LIBDCP_REEL_ASSET_H
+
#include "object.h"
#include "util.h"
#include "ref.h"
#include <memory>
+
namespace cxml {
class Node;
}
+
namespace xmlpp {
class Node;
}
+
namespace dcp {
+
class Asset;
+
/** @class ReelAsset
* @brief An entry in a <Reel> which refers to a use of a piece of content.
*
class ReelAsset : public Object
{
public:
+ /** Construct a ReelAsset
+ * @param id ID of this ReelAsset (which is that of the MXF, if there is one)
+ * @param edit_rate Edit rate for the asset
+ * @param intrinsic_duration Intrinsic duration of this asset
+ * @param entry_point Entry point to use in that asset
+ */
ReelAsset (std::string id, Fraction edit_rate, int64_t intrinsic_duration, int64_t entry_point);
+
explicit ReelAsset (std::shared_ptr<const cxml::Node>);
virtual xmlpp::Node* write_to_cpl (xmlpp::Node* node, Standard standard) const = 0;
return _duration;
}
+ /** @return <Duration>, or <IntrinsicDuration> - <EntryPoint> if <Duration> is not present */
int64_t actual_duration () const;
std::string annotation_text () const {
xmlpp::Node* write_to_cpl_asset (xmlpp::Node* node, Standard standard, boost::optional<std::string> hash) const;
- int64_t _intrinsic_duration; ///< The <IntrinsicDuration> from the reel's entry for this asset
+ int64_t _intrinsic_duration = 0; ///< The <IntrinsicDuration> from the reel's entry for this asset
boost::optional<int64_t> _duration; ///< The <Duration> from the reel's entry for this asset, if present
private:
/*
- Copyright (C) 2016-2017 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2016-2021 Carl Hetherington <cth@carlh.net>
This file is part of libdcp.
files in the program, then also delete it here.
*/
+
/** @file src/reel_atmos_asset.cc
- * @brief ReelAtmosAsset class.
+ * @brief ReelAtmosAsset class
*/
+
#include "atmos_asset.h"
#include "reel_atmos_asset.h"
#include <libcxml/cxml.h>
#include <libxml++/libxml++.h>
+
using std::string;
using std::pair;
using std::make_pair;
using std::shared_ptr;
using namespace dcp;
+
ReelAtmosAsset::ReelAtmosAsset (std::shared_ptr<AtmosAsset> asset, int64_t entry_point)
: ReelAsset (asset->id(), asset->edit_rate(), asset->intrinsic_duration(), entry_point)
, ReelMXF (asset, asset->key_id())
}
+
ReelAtmosAsset::ReelAtmosAsset (std::shared_ptr<const cxml::Node> node)
: ReelAsset (node)
, ReelMXF (node)
node->done ();
}
+
string
ReelAtmosAsset::cpl_node_name (Standard) const
{
return "axd:AuxData";
}
+
pair<string, string>
ReelAtmosAsset::cpl_node_namespace (Standard) const
{
- return make_pair ("http://www.dolby.com/schemas/2012/AD", "axd");
+ return { "http://www.dolby.com/schemas/2012/AD", "axd" };
}
+
string
ReelAtmosAsset::key_type () const
{
return "MDEK";
}
+
xmlpp::Node *
ReelAtmosAsset::write_to_cpl (xmlpp::Node* node, Standard standard) const
{
- xmlpp::Node* asset = write_to_cpl_asset (node, standard, hash());
+ auto asset = write_to_cpl_asset (node, standard, hash());
write_to_cpl_mxf (asset);
asset->add_child("axd:DataType")->add_child_text("urn:smpte:ul:060e2b34.04010105.0e090604.00000000");
return asset;
}
+
bool
ReelAtmosAsset::equals (shared_ptr<const ReelAtmosAsset> other, EqualityOptions opt, NoteHandler note) const
{
if (!asset_equals (other, opt, note)) {
return false;
}
+
if (!mxf_equals (other, opt, note)) {
return false;
}
/*
- Copyright (C) 2016-2017 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2016-2021 Carl Hetherington <cth@carlh.net>
This file is part of libdcp.
files in the program, then also delete it here.
*/
+
/** @file src/reel_atmos_asset.h
- * @brief ReelAtmosAsset class.
+ * @brief ReelAtmosAsset class
*/
+
#ifndef LIBDCP_REEL_ATMOS_ASSET_H
#define LIBDCP_REEL_ATMOS_ASSET_H
+
#include "reel_asset.h"
#include "atmos_asset.h"
#include "reel_mxf.h"
+
namespace dcp {
+
class AtmosAsset;
-/** @class ReelAtmosAsset
- * @brief Part of a Reel's description which refers to a Atmos MXF.
+
+/** @class ReelAtmosAsse
+ * @brief Part of a Reel's description which refers to a Atmos MXF
*/
class ReelAtmosAsset : public ReelAsset, public ReelMXF
{
std::pair<std::string, std::string> cpl_node_namespace (Standard) const;
};
+
}
+
#endif
/*
- Copyright (C) 2012-2017 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2021 Carl Hetherington <cth@carlh.net>
This file is part of libdcp.
files in the program, then also delete it here.
*/
+
/** @file src/reel_closed_caption_asset.cc
- * @brief ReelClosedCaptionAsset class.
+ * @brief ReelClosedCaptionAsset class
*/
+
#include "subtitle_asset.h"
#include "reel_closed_caption_asset.h"
#include "smpte_subtitle_asset.h"
#include "dcp_assert.h"
#include <libxml++/libxml++.h>
+
using std::string;
using std::pair;
using std::make_pair;
using boost::optional;
using namespace dcp;
+
ReelClosedCaptionAsset::ReelClosedCaptionAsset (std::shared_ptr<SubtitleAsset> asset, Fraction edit_rate, int64_t intrinsic_duration, int64_t entry_point)
: ReelAsset (asset->id(), edit_rate, intrinsic_duration, entry_point)
, ReelMXF (asset, dynamic_pointer_cast<SMPTESubtitleAsset>(asset) ? dynamic_pointer_cast<SMPTESubtitleAsset>(asset)->key_id() : optional<string>())
}
+
ReelClosedCaptionAsset::ReelClosedCaptionAsset (std::shared_ptr<const cxml::Node> node)
: ReelAsset (node)
, ReelMXF (node)
node->done ();
}
+
string
ReelClosedCaptionAsset::cpl_node_name (Standard standard) const
{
DCP_ASSERT (false);
}
+
pair<string, string>
ReelClosedCaptionAsset::cpl_node_namespace (Standard standard) const
{
DCP_ASSERT (false);
}
+
string
ReelClosedCaptionAsset::key_type () const
{
return "MDSK";
}
+
xmlpp::Node *
ReelClosedCaptionAsset::write_to_cpl (xmlpp::Node* node, Standard standard) const
{
- xmlpp::Node* asset = write_to_cpl_asset (node, standard, hash());
+ auto asset = write_to_cpl_asset (node, standard, hash());
write_to_cpl_mxf (asset);
if (_language) {
return asset;
}
+
bool
ReelClosedCaptionAsset::equals (shared_ptr<const ReelClosedCaptionAsset> other, EqualityOptions opt, NoteHandler note) const
{
/*
- Copyright (C) 2012-2017 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2021 Carl Hetherington <cth@carlh.net>
This file is part of libdcp.
files in the program, then also delete it here.
*/
+
/** @file src/reel_closed_caption_asset.h
- * @brief ReelClosedCaptionAsset class.
+ * @brief ReelClosedCaptionAsset class
*/
+
#ifndef LIBDCP_REEL_CLOSED_CAPTION_ASSET_H
#define LIBDCP_REEL_CLOSED_CAPTION_ASSET_H
+
#include "language_tag.h"
#include "subtitle_asset.h"
#include "reel_asset.h"
namespace dcp {
+
class SubtitleAsset;
+
/** @class ReelClosedCaptionAsset
- * @brief Part of a Reel's description which refers to a closed caption XML/MXF file.
+ * @brief Part of a Reel's description which refers to a closed caption XML/MXF file
*/
class ReelClosedCaptionAsset : public ReelAsset, public ReelMXF
{
boost::optional<std::string> _language;
};
+
}
+
#endif
files in the program, then also delete it here.
*/
+
#include "reel_markers_asset.h"
#include "raw_convert.h"
#include "dcp_assert.h"
#include <libxml++/libxml++.h>
+
using std::string;
using std::map;
using std::max;
using std::shared_ptr;
using namespace dcp;
+
ReelMarkersAsset::ReelMarkersAsset (Fraction edit_rate, int64_t intrinsic_duration, int64_t entry_point)
: ReelAsset (make_uuid(), edit_rate, intrinsic_duration, entry_point)
{
}
+
ReelMarkersAsset::ReelMarkersAsset (cxml::ConstNodePtr node)
: ReelAsset (node)
{
}
}
+
string
ReelMarkersAsset::cpl_node_name (Standard) const
{
return "MainMarkers";
}
+
void
ReelMarkersAsset::set (Marker m, Time t)
{
_markers[m] = t;
}
+
void
ReelMarkersAsset::unset (Marker m)
{
_markers.erase (m);
}
+
optional<Time>
ReelMarkersAsset::get (Marker m) const
{
return i->second;
}
+
xmlpp::Node*
ReelMarkersAsset::write_to_cpl (xmlpp::Node* node, Standard standard) const
{
int const tcr = edit_rate().numerator / edit_rate().denominator;
- xmlpp::Node* asset = write_to_cpl_asset (node, standard, optional<string>());
- xmlpp::Node* ml = asset->add_child("MarkerList");
- for (map<Marker, Time>::const_iterator i = _markers.begin(); i != _markers.end(); ++i) {
- xmlpp::Node* m = ml->add_child("Marker");
- m->add_child("Label")->add_child_text (marker_to_string(i->first));
- m->add_child("Offset")->add_child_text (raw_convert<string>(i->second.as_editable_units(tcr)));
+ auto asset = write_to_cpl_asset (node, standard, optional<string>());
+ auto ml = asset->add_child("MarkerList");
+ for (auto const& i: _markers) {
+ auto m = ml->add_child("Marker");
+ m->add_child("Label")->add_child_text(marker_to_string(i.first));
+ m->add_child("Offset")->add_child_text(raw_convert<string>(i.second.as_editable_units(tcr)));
}
return asset;
/*
- Copyright (C) 2019 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2019-2021 Carl Hetherington <cth@carlh.net>
This file is part of libdcp.
files in the program, then also delete it here.
*/
+
#include "reel_asset.h"
#include "dcp_time.h"
#include <map>
+
namespace dcp {
+
class ReelMarkersAsset : public ReelAsset
{
public:
std::map<Marker, Time> _markers;
};
+
}
/*
- Copyright (C) 2014-2017 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2014-2021 Carl Hetherington <cth@carlh.net>
This file is part of libdcp.
files in the program, then also delete it here.
*/
+
/** @file src/reel_mono_picture_asset.cc
- * @brief ReelMonoPictureAsset class.
+ * @brief ReelMonoPictureAsset class
*/
+
#include "reel_mono_picture_asset.h"
#include "mono_picture_asset.h"
#include <libcxml/cxml.h>
+
using std::string;
using std::shared_ptr;
using namespace dcp;
+
ReelMonoPictureAsset::ReelMonoPictureAsset (std::shared_ptr<MonoPictureAsset> asset, int64_t entry_point)
: ReelPictureAsset (asset, entry_point)
{
}
+
ReelMonoPictureAsset::ReelMonoPictureAsset (std::shared_ptr<const cxml::Node> node)
: ReelPictureAsset (node)
{
node->done ();
}
+
string
ReelMonoPictureAsset::cpl_node_name (Standard) const
{
/*
- Copyright (C) 2014-2019 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2014-2021 Carl Hetherington <cth@carlh.net>
This file is part of libdcp.
files in the program, then also delete it here.
*/
+
/** @file src/reel_mono_picture_asset.h
- * @brief ReelMonoPictureAsset class.
+ * @brief ReelMonoPictureAsset class
*/
+
#ifndef LIBDCP_REEL_MONO_PICTURE_ASSET_H
#define LIBDCP_REEL_MONO_PICTURE_ASSET_H
+
#include "reel_picture_asset.h"
#include "mono_picture_asset.h"
+
namespace dcp {
+
class MonoPictureAsset;
+
/** @class ReelMonoPictureAsset
- * @brief Part of a Reel's description which refers to a monoscopic picture asset.
+ * @brief Part of a Reel's description which refers to a monoscopic picture asset
*/
class ReelMonoPictureAsset : public ReelPictureAsset
{
std::string cpl_node_name (Standard standard) const;
};
+
}
+
#endif
/*
- Copyright (C) 2014-2016 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2014-2021 Carl Hetherington <cth@carlh.net>
This file is part of libdcp.
files in the program, then also delete it here.
*/
-/** @file src/reel_picture_asset.h
- * @brief ReelPictureAsset class.
+
+/** @file src/reel_picture_asset.cc
+ * @brief ReelPictureAsset class
*/
+
#include "reel_picture_asset.h"
#include "picture_asset.h"
#include "dcp_assert.h"
#include <iomanip>
#include <cmath>
+
using std::bad_cast;
using std::string;
using std::shared_ptr;
using boost::optional;
using namespace dcp;
+
ReelPictureAsset::ReelPictureAsset (shared_ptr<PictureAsset> asset, int64_t entry_point)
: ReelAsset (asset->id(), asset->edit_rate(), asset->intrinsic_duration(), entry_point)
, ReelMXF (asset, asset->key_id())
}
+
ReelPictureAsset::ReelPictureAsset (shared_ptr<const cxml::Node> node)
: ReelAsset (node)
, ReelMXF (node)
}
}
+
xmlpp::Node*
ReelPictureAsset::write_to_cpl (xmlpp::Node* node, Standard standard) const
{
- xmlpp::Node* asset = write_to_cpl_asset (node, standard, hash());
+ auto asset = write_to_cpl_asset (node, standard, hash());
asset->add_child("FrameRate")->add_child_text(String::compose("%1 %2", _frame_rate.numerator, _frame_rate.denominator));
if (standard == Standard::INTEROP) {
return asset;
}
+
string
ReelPictureAsset::key_type () const
{
return "MDIK";
}
+
bool
ReelPictureAsset::equals (shared_ptr<const ReelPictureAsset> other, EqualityOptions opt, NoteHandler note) const
{
return false;
}
- shared_ptr<const ReelPictureAsset> rpa = dynamic_pointer_cast<const ReelPictureAsset> (other);
+ auto rpa = dynamic_pointer_cast<const ReelPictureAsset>(other);
if (!rpa) {
return false;
}
files in the program, then also delete it here.
*/
+
/** @file src/reel_picture_asset.h
- * @brief ReelPictureAsset class.
+ * @brief ReelPictureAsset class
*/
+
#ifndef LIBDCP_REEL_PICTURE_ASSET_H
#define LIBDCP_REEL_PICTURE_ASSET_H
+
#include "reel_mxf.h"
#include "reel_asset.h"
#include "picture_asset.h"
+
namespace dcp {
+
/** @class ReelPictureAsset
- * @brief Part of a Reel's description which refers to a picture asset.
+ * @brief Part of a Reel's description which refers to a picture asset
*/
class ReelPictureAsset : public ReelAsset, public ReelMXF
{
Fraction _screen_aspect_ratio;
};
+
}
+
#endif
/*
- Copyright (C) 2014-2015 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2014-2021 Carl Hetherington <cth@carlh.net>
This file is part of libdcp.
files in the program, then also delete it here.
*/
+
/** @file src/reel_sound_asset.cc
- * @brief ReelSoundAsset class.
+ * @brief ReelSoundAsset class
*/
+
#include "reel_sound_asset.h"
#include "dcp_assert.h"
#include <libcxml/cxml.h>
#include <libxml++/libxml++.h>
+
using std::string;
using std::shared_ptr;
using namespace dcp;
+
ReelSoundAsset::ReelSoundAsset (shared_ptr<SoundAsset> asset, int64_t entry_point)
: ReelAsset (asset->id(), asset->edit_rate(), asset->intrinsic_duration(), entry_point)
, ReelMXF (asset, asset->key_id())
}
+
ReelSoundAsset::ReelSoundAsset (shared_ptr<const cxml::Node> node)
: ReelAsset (node)
, ReelMXF (node)
node->done ();
}
+
string
ReelSoundAsset::cpl_node_name (Standard) const
{
return "MainSound";
}
+
string
ReelSoundAsset::key_type () const
{
return "MDAK";
}
+
xmlpp::Node *
ReelSoundAsset::write_to_cpl (xmlpp::Node* node, Standard standard) const
{
- xmlpp::Node* asset = write_to_cpl_asset (node, standard, hash());
+ auto asset = write_to_cpl_asset (node, standard, hash());
write_to_cpl_mxf (asset);
return asset;
}
+
bool
ReelSoundAsset::equals (shared_ptr<const ReelSoundAsset> other, EqualityOptions opt, NoteHandler note) const
{
/*
- Copyright (C) 2014-2019 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2014-2021 Carl Hetherington <cth@carlh.net>
This file is part of libdcp.
files in the program, then also delete it here.
*/
+
/** @file src/reel_sound_asset.h
- * @brief ReelSoundAsset class.
+ * @brief ReelSoundAsset class
*/
+
#include "reel_mxf.h"
#include "reel_asset.h"
#include "sound_asset.h"
#include <memory>
#include <string>
+
namespace dcp {
+
/** @class ReelSoundAsset
- * @brief Part of a Reel's description which refers to a sound asset.
+ * @brief Part of a Reel's description which refers to a sound asset
*/
class ReelSoundAsset : public ReelAsset, public ReelMXF
{
std::string cpl_node_name (Standard standard) const;
};
+
}
/*
- Copyright (C) 2014-2019 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2014-2021 Carl Hetherington <cth@carlh.net>
This file is part of libdcp.
files in the program, then also delete it here.
*/
+
/** @file src/reel_stereo_picture_asset.cc
- * @brief ReelStereoPictureAsset class.
+ * @brief ReelStereoPictureAsset class
*/
+
#include "reel_stereo_picture_asset.h"
#include "stereo_picture_asset.h"
#include <libcxml/cxml.h>
+
using std::string;
using std::pair;
using std::make_pair;
using std::shared_ptr;
using namespace dcp;
+
ReelStereoPictureAsset::ReelStereoPictureAsset (std::shared_ptr<StereoPictureAsset> mxf, int64_t entry_point)
: ReelPictureAsset (mxf, entry_point)
{
}
+
ReelStereoPictureAsset::ReelStereoPictureAsset (std::shared_ptr<const cxml::Node> node)
: ReelPictureAsset (node)
{
node->done ();
}
+
string
ReelStereoPictureAsset::cpl_node_name (Standard) const
{
return "msp-cpl:MainStereoscopicPicture";
}
+
pair<string, string>
ReelStereoPictureAsset::cpl_node_attribute (Standard standard) const
{
switch (standard) {
case Standard::INTEROP:
- return make_pair ("xmlns:msp-cpl", "http://www.digicine.com/schemas/437-Y/2007/Main-Stereo-Picture-CPL");
+ return { "xmlns:msp-cpl", "http://www.digicine.com/schemas/437-Y/2007/Main-Stereo-Picture-CPL" };
case Standard::SMPTE:
- return make_pair ("xmlns:msp-cpl", "http://www.smpte-ra.org/schemas/429-10/2008/Main-Stereo-Picture-CPL");
+ return { "xmlns:msp-cpl", "http://www.smpte-ra.org/schemas/429-10/2008/Main-Stereo-Picture-CPL" };
}
DCP_ASSERT (false);
/*
- Copyright (C) 2014-2019 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2014-2021 Carl Hetherington <cth@carlh.net>
This file is part of libdcp.
files in the program, then also delete it here.
*/
+
/** @file src/reel_stereo_picture_asset.h
- * @brief ReelStereoPictureAsset class.
+ * @brief ReelStereoPictureAsset class
*/
+
#ifndef LIBDCP_REEL_STEREO_PICTURE_ASSET_H
#define LIBDCP_REEL_STEREO_PICTURE_ASSET_H
+
#include "reel_picture_asset.h"
#include "stereo_picture_asset.h"
+
namespace dcp {
+
class StereoPictureAsset;
+
/** @class ReelStereoPictureAsset
- * @brief Part of a Reel's description which refers to a stereoscopic picture asset.
+ * @brief Part of a Reel's description which refers to a stereoscopic picture asset
*/
class ReelStereoPictureAsset : public ReelPictureAsset
{
std::pair<std::string, std::string> cpl_node_attribute (Standard standard) const;
};
+
}
+
#endif
/*
- Copyright (C) 2012-2020 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2021 Carl Hetherington <cth@carlh.net>
This file is part of libdcp.
files in the program, then also delete it here.
*/
+
/** @file src/reel_subtitle_asset.cc
- * @brief ReelSubtitleAsset class.
+ * @brief ReelSubtitleAsset class
*/
+
#include "language_tag.h"
#include "subtitle_asset.h"
#include "reel_subtitle_asset.h"
#include "smpte_subtitle_asset.h"
#include <libxml++/libxml++.h>
+
using std::string;
using std::shared_ptr;
using std::dynamic_pointer_cast;
using boost::optional;
using namespace dcp;
+
ReelSubtitleAsset::ReelSubtitleAsset (std::shared_ptr<SubtitleAsset> asset, Fraction edit_rate, int64_t intrinsic_duration, int64_t entry_point)
: ReelAsset (asset->id(), edit_rate, intrinsic_duration, entry_point)
, ReelMXF (asset, dynamic_pointer_cast<SMPTESubtitleAsset>(asset) ? dynamic_pointer_cast<SMPTESubtitleAsset>(asset)->key_id() : optional<string>())
}
+
ReelSubtitleAsset::ReelSubtitleAsset (std::shared_ptr<const cxml::Node> node)
: ReelAsset (node)
, ReelMXF (node)
node->done ();
}
+
string
ReelSubtitleAsset::cpl_node_name (Standard) const
{
return "MainSubtitle";
}
+
string
ReelSubtitleAsset::key_type () const
{
return "MDSK";
}
+
xmlpp::Node *
ReelSubtitleAsset::write_to_cpl (xmlpp::Node* node, Standard standard) const
{
- xmlpp::Node* asset = write_to_cpl_asset (node, standard, hash());
+ auto asset = write_to_cpl_asset (node, standard, hash());
write_to_cpl_mxf (asset);
if (_language) {
asset->add_child("Language")->add_child_text(*_language);
return asset;
}
+
bool
ReelSubtitleAsset::equals (shared_ptr<const ReelSubtitleAsset> other, EqualityOptions opt, NoteHandler note) const
{
/*
- Copyright (C) 2012-2020 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2021 Carl Hetherington <cth@carlh.net>
This file is part of libdcp.
files in the program, then also delete it here.
*/
+
/** @file src/reel_subtitle_asset.h
* @brief ReelSubtitleAsset class.
*/
+
#ifndef LIBDCP_REEL_SUBTITLE_ASSET_H
#define LIBDCP_REEL_SUBTITLE_ASSET_H
+
#include "language_tag.h"
#include "reel_asset.h"
#include "reel_mxf.h"
#include "subtitle_asset.h"
+
struct verify_invalid_language1;
+
namespace dcp {
+
class SubtitleAsset;
+
/** @class ReelSubtitleAsset
- * @brief Part of a Reel's description which refers to a subtitle XML/MXF file.
+ * @brief Part of a Reel's description which refers to a subtitle XML/MXF file
*/
class ReelSubtitleAsset : public ReelAsset, public ReelMXF
{
boost::optional<std::string> _language;
};
+
}
+
#endif
/*
- Copyright (C) 2013-2015 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2013-2021 Carl Hetherington <cth@carlh.net>
This file is part of libdcp.
files in the program, then also delete it here.
*/
-#include "rgb_xyz.h"
-#include "openjpeg_image.h"
+
#include "colour_conversion.h"
-#include "transfer_function.h"
-#include "dcp_assert.h"
#include "compose.hpp"
+#include "dcp_assert.h"
+#include "openjpeg_image.h"
+#include "rgb_xyz.h"
+#include "transfer_function.h"
#include <cmath>
-using std::min;
-using std::max;
+
using std::cout;
+using std::make_shared;
+using std::max;
+using std::min;
using std::shared_ptr;
using boost::optional;
using namespace dcp;
-#define DCI_COEFFICIENT (48.0 / 52.37)
-
-/** Convert an XYZ image to RGBA.
- * @param xyz_image Image in XYZ.
- * @param conversion Colour conversion to use.
- * @param argb Buffer to fill with RGBA data. The format of the data is:
- *
- * <pre>
- * Byte /- 0 -------|- 1 --------|- 2 --------|- 3 --------|- 4 --------|- 5 --------| ...
- * |(0, 0) Blue|(0, 0)Green |(0, 0) Red |(0, 0) Alpha|(0, 1) Blue |(0, 1) Green| ...
- * </pre>
- *
- * So that the first byte is the blue component of the pixel at x=0, y=0, the second
- * is the green component, and so on.
- *
- * Lines are packed so that the second row directly follows the first.
- */
+
+static auto constexpr DCI_COEFFICIENT = 48.0 / 52.37;
+
+
void
dcp::xyz_to_rgba (
std::shared_ptr<const OpenJPEGImage> xyz_image,
}
}
-/** Convert an XYZ image to 48bpp RGB.
- * @param xyz_image Frame in XYZ.
- * @param conversion Colour conversion to use.
- * @param rgb Buffer to fill with RGB data. Format is packed RGB
- * 16:16:16, 48bpp, 16R, 16G, 16B, with the 2-byte value for each
- * R/G/B component stored as little-endian; i.e. AV_PIX_FMT_RGB48LE.
- * @param stride Stride for RGB data in bytes.
- * @param note Optional handler for any notes that may be made during the conversion (e.g. when clamping occurs).
- */
+
void
dcp::xyz_to_rgb (
shared_ptr<const OpenJPEGImage> xyz_image,
}
}
-/** @param conversion Colour conversion.
- * @param matrix Filled in with the product of the RGB to XYZ matrix, the Bradford transform and the DCI companding.
- */
void
dcp::combined_rgb_to_xyz (ColourConversion const & conversion, double* matrix)
{
* DCI_COEFFICIENT * 65535;
}
-/** @param rgb RGB data; packed RGB 16:16:16, 48bpp, 16R, 16G, 16B,
- * with the 2-byte value for each R/G/B component stored as
- * little-endian; i.e. AV_PIX_FMT_RGB48LE.
- * @param size size of RGB image in pixels.
- * @param size stride of RGB data in pixels.
- */
+
shared_ptr<dcp::OpenJPEGImage>
dcp::rgb_to_xyz (
uint8_t const * rgb,
optional<NoteHandler> note
)
{
- shared_ptr<OpenJPEGImage> xyz (new OpenJPEGImage (size));
+ auto xyz = make_shared<OpenJPEGImage>(size);
struct {
double r, g, b;
double x, y, z;
} d;
- double const * lut_in = conversion.in()->lut (12, false);
- double const * lut_out = conversion.out()->lut (16, true);
+ auto const * lut_in = conversion.in()->lut (12, false);
+ auto const * lut_out = conversion.out()->lut (16, true);
/* This is is the product of the RGB to XYZ matrix, the Bradford transform and the DCI companding */
double fast_matrix[9];
int* xyz_y = xyz->data (1);
int* xyz_z = xyz->data (2);
for (int y = 0; y < size.height; ++y) {
- uint16_t const * p = reinterpret_cast<uint16_t const *> (rgb + y * stride);
+ auto p = reinterpret_cast<uint16_t const *> (rgb + y * stride);
for (int x = 0; x < size.width; ++x) {
/* In gamma LUT (converting 16-bit to 12-bit) */
/*
- Copyright (C) 2013-2015 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2013-2021 Carl Hetherington <cth@carlh.net>
This file is part of libdcp.
files in the program, then also delete it here.
*/
+
#include "types.h"
#include <memory>
#include <boost/optional.hpp>
#include <stdint.h>
+
namespace dcp {
+
class OpenJPEGImage;
class Image;
class ColourConversion;
+
+/** Convert an XYZ image to RGBA.
+ * @param xyz_image Image in XYZ.
+ * @param conversion Colour conversion to use.
+ * @param argb Buffer to fill with RGBA data. The format of the data is:
+ *
+ * <pre>
+ * Byte /- 0 -------|- 1 --------|- 2 --------|- 3 --------|- 4 --------|- 5 --------| ...
+ * |(0, 0) Blue|(0, 0)Green |(0, 0) Red |(0, 0) Alpha|(0, 1) Blue |(0, 1) Green| ...
+ * </pre>
+ *
+ * So that the first byte is the blue component of the pixel at x=0, y=0, the second
+ * is the green component, and so on.
+ *
+ * Lines are packed so that the second row directly follows the first.
+ */
extern void xyz_to_rgba (
std::shared_ptr<const OpenJPEGImage>,
ColourConversion const & conversion,
int stride
);
+
+/** Convert an XYZ image to 48bpp RGB.
+ * @param xyz_image Frame in XYZ.
+ * @param conversion Colour conversion to use.
+ * @param rgb Buffer to fill with RGB data. Format is packed RGB
+ * 16:16:16, 48bpp, 16R, 16G, 16B, with the 2-byte value for each
+ * R/G/B component stored as little-endian; i.e. AV_PIX_FMT_RGB48LE.
+ * @param stride Stride for RGB data in bytes.
+ * @param note Optional handler for any notes that may be made during the conversion (e.g. when clamping occurs).
+ */
extern void xyz_to_rgb (
std::shared_ptr<const OpenJPEGImage>,
ColourConversion const & conversion,
boost::optional<NoteHandler> note = boost::optional<NoteHandler> ()
);
+
+/** @param rgb RGB data; packed RGB 16:16:16, 48bpp, 16R, 16G, 16B,
+ * with the 2-byte value for each R/G/B component stored as
+ * little-endian; i.e. AV_PIX_FMT_RGB48LE.
+ * @param size size of RGB image in pixels.
+ * @param size stride of RGB data in pixels.
+ */
extern std::shared_ptr<OpenJPEGImage> rgb_to_xyz (
uint8_t const * rgb,
dcp::Size size,
boost::optional<NoteHandler> note = boost::optional<NoteHandler> ()
);
+
+/** @param conversion Colour conversion.
+ * @param matrix Filled in with the product of the RGB to XYZ matrix, the Bradford transform and the DCI companding.
+ */
extern void combined_rgb_to_xyz (ColourConversion const & conversion, double* matrix);
}
/*
- Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2021 Carl Hetherington <cth@carlh.net>
This file is part of libdcp.
files in the program, then also delete it here.
*/
+
/** @file src/s_gamut3_transfer_function.cc
- * @brief SGamut3TransferFunction class.
+ * @brief SGamut3TransferFunction class
*/
+
#include "s_gamut3_transfer_function.h"
#include <cmath>
+
using std::pow;
using std::shared_ptr;
using std::dynamic_pointer_cast;
using namespace dcp;
+
double *
SGamut3TransferFunction::make_lut (int bit_depth, bool inverse) const
{
double* lut = new double[bit_length];
if (inverse) {
for (int i = 0; i < bit_length; ++i) {
- double const p = static_cast<double> (i) / (bit_length - 1);
+ auto const p = static_cast<double>(i) / (bit_length - 1);
if (p >= (0.01125 / 1023)) {
lut[i] = (420 + log10((p + 0.01) / (0.18 + 0.01)) * 261.5) / 1023;
} else {
}
} else {
for (int i = 0; i < bit_length; ++i) {
- double const p = static_cast<double> (i) / (bit_length - 1);
+ auto const p = static_cast<double>(i) / (bit_length - 1);
if (p >= (171.2102946929 / 1023)) {
lut[i] = pow(10, ((p * 1023 - 420) / 261.5)) * (0.18 + 0.01) - 0.01;
} else {
return lut;
}
+
bool
SGamut3TransferFunction::about_equal (shared_ptr<const TransferFunction> other, double) const
{
- shared_ptr<const SGamut3TransferFunction> o = dynamic_pointer_cast<const SGamut3TransferFunction> (other);
+ auto o = dynamic_pointer_cast<const SGamut3TransferFunction> (other);
return static_cast<bool> (o);
}
/*
- Copyright (C) 2016 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2016-2021 Carl Hetherington <cth@carlh.net>
This file is part of libdcp.
files in the program, then also delete it here.
*/
+
/** @file src/s_gamut3_transfer_function.h
* @brief SGamut3TransferFunction class.
*/
+
#include "transfer_function.h"
+
namespace dcp {
+
class SGamut3TransferFunction : public TransferFunction
{
public:
double * make_lut (int bit_depth, bool inverse) const;
};
+
}
/*
- Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2021 Carl Hetherington <cth@carlh.net>
This file is part of libdcp.
files in the program, then also delete it here.
*/
+
+/** @file src/smpte_load_font_node.cc
+ * @brief SMPTELoadFontNode class
+ */
+
+
#include "smpte_load_font_node.h"
#include "util.h"
#include <libcxml/cxml.h>
+
using std::string;
using std::shared_ptr;
using namespace dcp;
+
SMPTELoadFontNode::SMPTELoadFontNode (string id, string urn_)
: LoadFontNode (id)
, urn (urn_)
}
+
SMPTELoadFontNode::SMPTELoadFontNode (shared_ptr<const cxml::Node> node)
: LoadFontNode (node->string_attribute ("ID"))
, urn (remove_urn_uuid (node->content()))
}
+
bool
dcp::operator== (SMPTELoadFontNode const & a, SMPTELoadFontNode const & b)
{
return a.id == b.id && a.urn == b.urn;
}
+
bool
dcp::operator!= (SMPTELoadFontNode const & a, SMPTELoadFontNode const & b)
{
/*
- Copyright (C) 2012-2015 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2021 Carl Hetherington <cth@carlh.net>
This file is part of libdcp.
files in the program, then also delete it here.
*/
+
/** @file src/smpte_load_font_node.h
* @brief SMPTELoadFontNode class.
*/
+
#include "load_font_node.h"
#include <memory>
#include <boost/optional.hpp>
+
namespace cxml {
class Node;
}
+
namespace dcp {
+
/** @class SMPTELoadFontNode
- * @brief Parser for LoadFont nodes from SMPTE subtitle XML.
+ * @brief Parser for LoadFont nodes from SMPTE subtitle XML
*/
class SMPTELoadFontNode : public LoadFontNode
{
std::string urn;
};
+
bool operator== (SMPTELoadFontNode const & a, SMPTELoadFontNode const & b);
bool operator!= (SMPTELoadFontNode const & a, SMPTELoadFontNode const & b);
+
}
/*
- Copyright (C) 2012-2019 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2021 Carl Hetherington <cth@carlh.net>
This file is part of libdcp.
files in the program, then also delete it here.
*/
+
/** @file src/smpte_subtitle_asset.cc
- * @brief SMPTESubtitleAsset class.
+ * @brief SMPTESubtitleAsset class
*/
+
#include "smpte_subtitle_asset.h"
#include "smpte_load_font_node.h"
#include "exceptions.h"
#include <libxml++/libxml++.h>
#include <boost/algorithm/string.hpp>
+
using std::string;
using std::list;
using std::vector;
using boost::starts_with;
using namespace dcp;
+
static string const subtitle_smpte_ns = "http://www.smpte-ra.org/schemas/428-7/2010/DCST";
+
SMPTESubtitleAsset::SMPTESubtitleAsset ()
: MXF (Standard::SMPTE)
- , _intrinsic_duration (0)
, _edit_rate (24, 1)
, _time_code_rate (24)
- , _xml_id (make_uuid ())
+ , _xml_id (make_uuid())
{
}
-/** Construct a SMPTESubtitleAsset by reading an MXF or XML file.
- * @param file Filename.
- */
+
SMPTESubtitleAsset::SMPTESubtitleAsset (boost::filesystem::path file)
: SubtitleAsset (file)
{
- shared_ptr<cxml::Document> xml (new cxml::Document ("SubtitleReel"));
+ auto xml = make_shared<cxml::Document>("SubtitleReel");
- shared_ptr<ASDCP::TimedText::MXFReader> reader (new ASDCP::TimedText::MXFReader ());
- Kumu::Result_t r = Kumu::RESULT_OK;
+ auto reader = make_shared<ASDCP::TimedText::MXFReader>();
+ auto r = Kumu::RESULT_OK;
{
ASDCPErrorSuspender sus;
r = reader->OpenRead (_file->string().c_str ());
}
- if (!ASDCP_FAILURE (r)) {
+ if (!ASDCP_FAILURE(r)) {
/* MXF-wrapped */
ASDCP::WriterInfo info;
reader->FillWriterInfo (info);
reader->ReadTimedTextResource (_raw_xml);
xml->read_string (_raw_xml);
parse_xml (xml);
- read_mxf_descriptor (reader, shared_ptr<DecryptionContext> (new DecryptionContext (optional<Key>(), Standard::SMPTE)));
+ read_mxf_descriptor (reader, make_shared<DecryptionContext>(optional<Key>(), Standard::SMPTE));
}
} else {
/* Plain XML */
try {
_raw_xml = dcp::file_to_string (file);
- xml.reset (new cxml::Document ("SubtitleReel"));
+ xml = make_shared<cxml::Document>("SubtitleReel");
xml->read_file (file);
parse_xml (xml);
_id = _xml_id = remove_urn_uuid (xml->string_child ("Id"));
ReadError (
String::compose (
"Failed to read subtitle file %1; MXF failed with %2, XML failed with %3",
- file, static_cast<int> (r), e.what ()
+ file, static_cast<int>(r), e.what()
)
)
);
}
}
+
void
SMPTESubtitleAsset::parse_xml (shared_ptr<cxml::Document> xml)
{
_time_code_rate = xml->number_child<int> ("TimeCodeRate");
if (xml->optional_string_child ("StartTime")) {
- _start_time = Time (xml->string_child ("StartTime"), _time_code_rate);
+ _start_time = Time (xml->string_child("StartTime"), _time_code_rate);
}
/* Now we need to drop down to xmlpp */
_intrinsic_duration = latest_subtitle_out().as_editable_units (_edit_rate.numerator / _edit_rate.denominator);
}
+
void
SMPTESubtitleAsset::read_mxf_descriptor (shared_ptr<ASDCP::TimedText::MXFReader> reader, shared_ptr<DecryptionContext> dec)
{
reader->ReadAncillaryResource (i->ResourceID, buffer, dec->context(), dec->hmac());
char id[64];
- Kumu::bin2UUIDhex (i->ResourceID, ASDCP::UUIDlen, id, sizeof (id));
+ Kumu::bin2UUIDhex (i->ResourceID, ASDCP::UUIDlen, id, sizeof(id));
shared_array<uint8_t> data (new uint8_t[buffer.Size()]);
memcpy (data.get(), buffer.RoData(), buffer.Size());
}
}
- /* Get intrinsic duration */
_intrinsic_duration = descriptor.ContainerDuration;
}
+
void
SMPTESubtitleAsset::set_key (Key key)
{
/* See if we already have a key; if we do, and we have a file, we'll already
have read that file.
*/
- bool const had_key = static_cast<bool> (_key);
+ auto const had_key = static_cast<bool>(_key);
MXF::set_key (key);
auto dec = make_shared<DecryptionContext>(key, Standard::SMPTE);
reader->ReadTimedTextResource (_raw_xml, dec->context(), dec->hmac());
- shared_ptr<cxml::Document> xml (new cxml::Document ("SubtitleReel"));
+ auto xml = make_shared<cxml::Document>("SubtitleReel");
xml->read_string (_raw_xml);
parse_xml (xml);
read_mxf_descriptor (reader, dec);
}
+
vector<shared_ptr<LoadFontNode>>
SMPTESubtitleAsset::load_font_nodes () const
{
vector<shared_ptr<LoadFontNode>> lf;
- copy (_load_font_nodes.begin(), _load_font_nodes.end(), back_inserter (lf));
+ copy (_load_font_nodes.begin(), _load_font_nodes.end(), back_inserter(lf));
return lf;
}
+
bool
SMPTESubtitleAsset::valid_mxf (boost::filesystem::path file)
{
ASDCP::TimedText::MXFReader reader;
Kumu::DefaultLogSink().UnsetFilterFlag(Kumu::LOG_ALLOW_ALL);
- Kumu::Result_t r = reader.OpenRead (file.string().c_str ());
+ auto r = reader.OpenRead (file.string().c_str ());
Kumu::DefaultLogSink().SetFilterFlag(Kumu::LOG_ALLOW_ALL);
return !ASDCP_FAILURE (r);
}
+
string
SMPTESubtitleAsset::xml_as_string () const
{
xmlpp::Document doc;
- xmlpp::Element* root = doc.create_root_node ("dcst:SubtitleReel");
+ auto root = doc.create_root_node ("dcst:SubtitleReel");
root->set_namespace_declaration (subtitle_smpte_ns, "dcst");
root->set_namespace_declaration ("http://www.w3.org/2001/XMLSchema", "xs");
return doc.write_to_string ("UTF-8");
}
-/** Write this content to a MXF file */
+
void
SMPTESubtitleAsset::write (boost::filesystem::path p) const
{
buffer.SetData (data_copy.data(), data_copy.size());
buffer.Size (j->data.size());
r = writer.WriteAncillaryResource (buffer, enc.context(), enc.hmac());
- if (ASDCP_FAILURE (r)) {
+ if (ASDCP_FAILURE(r)) {
boost::throw_exception (MXFFileError ("could not write font to timed text resource", p.string(), r));
}
}
return false;
}
- shared_ptr<const SMPTESubtitleAsset> other = dynamic_pointer_cast<const SMPTESubtitleAsset> (other_asset);
+ auto other = dynamic_pointer_cast<const SMPTESubtitleAsset>(other_asset);
if (!other) {
note (NoteType::ERROR, "Subtitles are in different standards");
return false;
return true;
}
+
void
SMPTESubtitleAsset::add_font (string load_id, dcp::ArrayData data)
{
string const uuid = make_uuid ();
_fonts.push_back (Font(load_id, uuid, data));
- _load_font_nodes.push_back (shared_ptr<SMPTELoadFontNode> (new SMPTELoadFontNode (load_id, uuid)));
+ _load_font_nodes.push_back (make_shared<SMPTELoadFontNode>(load_id, uuid));
}
+
void
SMPTESubtitleAsset::add (shared_ptr<Subtitle> s)
{
/*
- Copyright (C) 2012-2020 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2021 Carl Hetherington <cth@carlh.net>
This file is part of libdcp.
files in the program, then also delete it here.
*/
+
/** @file src/smpte_subtitle_asset.h
- * @brief SMPTESubtitleAsset class.
+ * @brief SMPTESubtitleAsset class
*/
+
#include "subtitle_asset.h"
#include "language_tag.h"
#include "local_time.h"
#include "crypto_context.h"
#include <boost/filesystem.hpp>
+
namespace ASDCP {
namespace TimedText {
class MXFReader;
}
}
+
struct verify_invalid_language1;
struct verify_invalid_language2;
+
namespace dcp {
+
class SMPTELoadFontNode;
+
/** @class SMPTESubtitleAsset
- * @brief A set of subtitles to be read and/or written in the SMPTE format.
+ * @brief A set of subtitles to be read and/or written in the SMPTE format
*/
class SMPTESubtitleAsset : public SubtitleAsset, public MXF
{
public:
SMPTESubtitleAsset ();
- /** @param file File name
+ /** Construct a SMPTESubtitleAsset by reading an MXF or XML file
+ * @param file Filename
*/
explicit SMPTESubtitleAsset (boost::filesystem::path file);
std::vector<std::shared_ptr<LoadFontNode>> load_font_nodes () const;
std::string xml_as_string () const;
+
+ /** Write this content to a MXF file */
void write (boost::filesystem::path path) const;
+
void add (std::shared_ptr<Subtitle>);
void add_font (std::string id, dcp::ArrayData data);
void set_key (Key key);
}
/** @return title of the film that these subtitles are for,
- * to be presented to the user.
+ * to be presented to the user
*/
std::string content_title_text () const {
return _content_title_text;
return _annotation_text;
}
- /** @return file creation time and date */
+ /** @return file issue time and date */
LocalTime issue_date () const {
return _issue_date;
}
/** The total length of this content in video frames. The amount of
* content presented may be less than this.
*/
- int64_t _intrinsic_duration;
+ int64_t _intrinsic_duration = 0;
/** <ContentTitleText> from the asset */
std::string _content_title_text;
/** This is stored and returned as a string so that we can tolerate non-RFC-5646 strings,
LocalTime _issue_date;
boost::optional<int> _reel_number;
Fraction _edit_rate;
- int _time_code_rate;
+ int _time_code_rate = 0;
boost::optional<Time> _start_time;
std::vector<std::shared_ptr<SMPTELoadFontNode>> _load_font_nodes;
std::string _xml_id;
};
+
}
/*
- Copyright (C) 2012-2020 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2021 Carl Hetherington <cth@carlh.net>
This file is part of libdcp.
files in the program, then also delete it here.
*/
-/** @file src/sound_mxf.cc
- * @brief SoundAsset class.
+
+/** @file src/sound_asset.cc
+ * @brief SoundAsset class
*/
+
#include "sound_asset.h"
#include "util.h"
#include "exceptions.h"
#include <boost/filesystem.hpp>
#include <stdexcept>
+
using std::string;
using std::vector;
using std::list;
, _language ("en-US")
{
ASDCP::PCM::MXFReader 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));
+ auto 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::PCM::AudioDescriptor desc;
- if (ASDCP_FAILURE (reader.FillAudioDescriptor (desc))) {
- boost::throw_exception (ReadError ("could not read audio MXF information"));
+ if (ASDCP_FAILURE (reader.FillAudioDescriptor(desc))) {
+ boost::throw_exception (ReadError("could not read audio MXF information"));
}
_sampling_rate = desc.AudioSamplingRate.Numerator / desc.AudioSamplingRate.Denominator;
_intrinsic_duration = desc.ContainerDuration;
ASDCP::WriterInfo info;
- if (ASDCP_FAILURE (reader.FillWriterInfo (info))) {
- boost::throw_exception (ReadError ("could not read audio MXF information"));
+ if (ASDCP_FAILURE (reader.FillWriterInfo(info))) {
+ boost::throw_exception (ReadError("could not read audio MXF information"));
}
ASDCP::MXF::SoundfieldGroupLabelSubDescriptor* soundfield;
- ASDCP::Result_t rr = reader.OP1aHeader().GetMDObjectByType(
+ auto rr = reader.OP1aHeader().GetMDObjectByType(
asdcp_smpte_dict->ul(ASDCP::MDD_SoundfieldGroupLabelSubDescriptor),
reinterpret_cast<ASDCP::MXF::InterchangeObject**>(&soundfield)
);
_id = read_writer_info (info);
}
+
SoundAsset::SoundAsset (Fraction edit_rate, int sampling_rate, int channels, LanguageTag language, Standard standard)
: MXF (standard)
, _edit_rate (edit_rate)
- , _intrinsic_duration (0)
, _channels (channels)
, _sampling_rate (sampling_rate)
, _language (language.to_string())
}
+
bool
SoundAsset::equals (shared_ptr<const Asset> other, EqualityOptions opt, NoteHandler note) const
{
ASDCP::PCM::MXFReader reader_A;
- DCP_ASSERT (file ());
- Kumu::Result_t r = reader_A.OpenRead (file()->string().c_str());
- if (ASDCP_FAILURE (r)) {
- boost::throw_exception (MXFFileError ("could not open MXF file for reading", file()->string(), r));
+ DCP_ASSERT (file());
+ auto r = reader_A.OpenRead (file()->string().c_str());
+ if (ASDCP_FAILURE(r)) {
+ boost::throw_exception (MXFFileError("could not open MXF file for reading", file()->string(), r));
}
ASDCP::PCM::MXFReader reader_B;
r = reader_B.OpenRead (other->file()->string().c_str());
if (ASDCP_FAILURE (r)) {
- boost::throw_exception (MXFFileError ("could not open MXF file for reading", other->file()->string(), r));
+ boost::throw_exception (MXFFileError("could not open MXF file for reading", other->file()->string(), r));
}
ASDCP::PCM::AudioDescriptor desc_A;
- if (ASDCP_FAILURE (reader_A.FillAudioDescriptor (desc_A))) {
+ if (ASDCP_FAILURE (reader_A.FillAudioDescriptor(desc_A))) {
boost::throw_exception (ReadError ("could not read audio MXF information"));
}
ASDCP::PCM::AudioDescriptor desc_B;
- if (ASDCP_FAILURE (reader_B.FillAudioDescriptor (desc_B))) {
+ if (ASDCP_FAILURE (reader_B.FillAudioDescriptor(desc_B))) {
boost::throw_exception (ReadError ("could not read audio MXF information"));
}
/* XXX */
}
- shared_ptr<const SoundAsset> other_sound = dynamic_pointer_cast<const SoundAsset> (other);
+ auto other_sound = dynamic_pointer_cast<const SoundAsset> (other);
- shared_ptr<const SoundAssetReader> reader = start_read ();
- shared_ptr<const SoundAssetReader> other_reader = other_sound->start_read ();
+ auto reader = start_read ();
+ auto other_reader = other_sound->start_read ();
for (int i = 0; i < _intrinsic_duration; ++i) {
- shared_ptr<const SoundFrame> frame_A = reader->get_frame (i);
- shared_ptr<const SoundFrame> frame_B = other_reader->get_frame (i);
+ auto frame_A = reader->get_frame (i);
+ auto frame_B = other_reader->get_frame (i);
if (frame_A->size() != frame_B->size()) {
note (NoteType::ERROR, String::compose ("sizes of audio data for frame %1 differ", i));
}
if (memcmp (frame_A->data(), frame_B->data(), frame_A->size()) != 0) {
- for (int sample= 0; sample < frame_A->samples(); ++sample) {
+ for (int sample = 0; sample < frame_A->samples(); ++sample) {
for (int channel = 0; channel < frame_A->channels(); ++channel) {
int32_t const d = abs(frame_A->get(channel, sample) - frame_B->get(channel, sample));
if (d > opt.max_audio_sample_error) {
return true;
}
+
shared_ptr<SoundAssetWriter>
SoundAsset::start_write (boost::filesystem::path file, vector<Channel> active_channels, bool atmos_sync)
{
return shared_ptr<SoundAssetWriter> (new SoundAssetWriter(this, file, active_channels, atmos_sync));
}
+
shared_ptr<SoundAssetReader>
SoundAsset::start_read () const
{
- return shared_ptr<SoundAssetReader> (new SoundAssetReader (this, key(), standard()));
+ return shared_ptr<SoundAssetReader> (new SoundAssetReader(this, key(), standard()));
}
+
string
SoundAsset::static_pkl_type (Standard standard)
{
}
}
+
bool
SoundAsset::valid_mxf (boost::filesystem::path file)
{
ASDCP::PCM::MXFReader reader;
- Kumu::Result_t r = reader.OpenRead (file.string().c_str ());
+ Kumu::Result_t r = reader.OpenRead (file.string().c_str());
return !ASDCP_FAILURE (r);
}
/*
- Copyright (C) 2012-2020 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2021 Carl Hetherington <cth@carlh.net>
This file is part of libdcp.
files in the program, then also delete it here.
*/
+
/** @file src/sound_asset.h
* @brief SoundAsset class
*/
+
#ifndef LIBDCP_SOUND_ASSET_H
#define LIBDCP_SOUND_ASSET_H
+
#include "mxf.h"
#include "types.h"
#include "language_tag.h"
class SoundAsset;
}
+
extern std::shared_ptr<dcp::SoundAsset> simple_sound (
boost::filesystem::path path, std::string suffix, dcp::MXFMetadata mxf_meta, std::string language, int frames, int sample_rate
);
namespace dcp
{
+
class SoundAssetWriter;
+
/** @class SoundAsset
* @brief Representation of a sound asset
*/
/** The total length of this content in video frames. The amount of
* content presented may be less than this.
*/
- int64_t _intrinsic_duration;
- int _channels; ///< number of channels
- int _sampling_rate; ///< sampling rate in Hz
+ int64_t _intrinsic_duration = 0;
+ int _channels = 0; ///< number of channels
+ int _sampling_rate = 0; ///< sampling rate in Hz
std::string _language;
};
+
}
+
#endif
/*
- Copyright (C) 2016 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2016-2021 Carl Hetherington <cth@carlh.net>
This file is part of libdcp.
files in the program, then also delete it here.
*/
+
+/** @file src/sound_asset_reader.h
+ * @brief SoundAssetReader typedef
+ */
+
+
#include "asset_reader.h"
#include "sound_frame.h"
+
namespace dcp {
+
typedef AssetReader<ASDCP::PCM::MXFReader, SoundFrame> SoundAssetReader;
+
}
files in the program, then also delete it here.
*/
+
+/** @file src/sound_asset_writer.cc
+ * @brief SoundAssetWriter class
+ */
+
+
#include "bitstream.h"
#include "sound_asset_writer.h"
#include "sound_asset.h"
#include <asdcp/Metadata.h>
#include <iostream>
+
using std::min;
using std::max;
using std::cout;
ASDCP::PCM::AudioDescriptor desc;
};
+
SoundAssetWriter::SoundAssetWriter (SoundAsset* asset, boost::filesystem::path file, vector<Channel> active_channels, bool sync)
: AssetWriter (asset, file)
, _state (new SoundAssetWriter::ASDCPState)
, _asset (asset)
- , _frame_buffer_offset (0)
, _sync (sync)
- , _sync_packet (0)
, _active_channels (active_channels)
{
DCP_ASSERT (!_sync || _asset->channels() >= 14);
_state->desc.EditRate = ASDCP::Rational (_asset->edit_rate().numerator, _asset->edit_rate().denominator);
_state->desc.AudioSamplingRate = ASDCP::Rational (_asset->sampling_rate(), 1);
_state->desc.Locked = 0;
- _state->desc.ChannelCount = _asset->channels ();
+ _state->desc.ChannelCount = _asset->channels();
_state->desc.QuantizationBits = 24;
_state->desc.BlockAlign = 3 * _asset->channels();
_state->desc.AvgBps = _asset->sampling_rate() * _state->desc.BlockAlign;
void
SoundAssetWriter::start ()
{
- Kumu::Result_t r = _state->mxf_writer.OpenWrite (_file.string().c_str(), _state->writer_info, _state->desc);
- if (ASDCP_FAILURE (r)) {
- boost::throw_exception (FileError ("could not open audio MXF for writing", _file.string(), r));
+ auto r = _state->mxf_writer.OpenWrite (_file.string().c_str(), _state->writer_info, _state->desc);
+ if (ASDCP_FAILURE(r)) {
+ boost::throw_exception (FileError("could not open audio MXF for writing", _file.string(), r));
}
if (_asset->standard() == Standard::SMPTE && !_active_channels.empty()) {
- ASDCP::MXF::WaveAudioDescriptor* essence_descriptor = 0;
+ ASDCP::MXF::WaveAudioDescriptor* essence_descriptor = nullptr;
_state->mxf_writer.OP1aHeader().GetMDObjectByType(
asdcp_smpte_dict->ul(ASDCP::MDD_WaveAudioDescriptor), reinterpret_cast<ASDCP::MXF::InterchangeObject**>(&essence_descriptor)
);
DCP_ASSERT (essence_descriptor);
essence_descriptor->ChannelAssignment = asdcp_smpte_dict->ul(ASDCP::MDD_DCAudioChannelCfg_MCA);
- ASDCP::MXF::SoundfieldGroupLabelSubDescriptor* soundfield = new ASDCP::MXF::SoundfieldGroupLabelSubDescriptor(asdcp_smpte_dict);
+ auto soundfield = new ASDCP::MXF::SoundfieldGroupLabelSubDescriptor(asdcp_smpte_dict);
GenRandomValue (soundfield->MCALinkID);
soundfield->RFC5646SpokenLanguage = _asset->language();
essence_descriptor->SubDescriptors.push_back(soundfield->InstanceUID);
for (auto i: _active_channels) {
- ASDCP::MXF::AudioChannelLabelSubDescriptor* channel = new ASDCP::MXF::AudioChannelLabelSubDescriptor(asdcp_smpte_dict);
+ auto channel = new ASDCP::MXF::AudioChannelLabelSubDescriptor(asdcp_smpte_dict);
GenRandomValue (channel->MCALinkID);
channel->SoundfieldGroupLinkID = soundfield->MCALinkID;
channel->MCAChannelID = static_cast<int>(i) + 1;
}
-/** @param data Pointer an array of float pointers, one for each channel.
- * @param frames Number of frames i.e. number of floats that are given for each channel.
- */
void
SoundAssetWriter::write (float const * const * data, int frames)
{
}
_frame_buffer_offset += 3 * ch;
- DCP_ASSERT (_frame_buffer_offset <= int (_state->frame_buffer.Capacity()));
+ DCP_ASSERT (_frame_buffer_offset <= int(_state->frame_buffer.Capacity()));
/* Finish the MXF frame if required */
if (_frame_buffer_offset == int (_state->frame_buffer.Capacity())) {
void
SoundAssetWriter::write_current_frame ()
{
- ASDCP::Result_t const r = _state->mxf_writer.WriteFrame (_state->frame_buffer, _crypto_context->context(), _crypto_context->hmac());
- if (ASDCP_FAILURE (r)) {
- boost::throw_exception (MiscError (String::compose ("could not write audio MXF frame (%1)", int (r))));
+ auto const r = _state->mxf_writer.WriteFrame (_state->frame_buffer, _crypto_context->context(), _crypto_context->hmac());
+ if (ASDCP_FAILURE(r)) {
+ boost::throw_exception (MiscError(String::compose("could not write audio MXF frame (%1)", static_cast<int>(r))));
}
++_frames_written;
}
if (_started) {
- ASDCP::Result_t const r = _state->mxf_writer.Finalize();
+ auto const r = _state->mxf_writer.Finalize();
if (ASDCP_FAILURE(r)) {
- boost::throw_exception (MiscError (String::compose ("could not finalise audio MXF (%1)", int(r))));
+ boost::throw_exception (MiscError(String::compose ("could not finalise audio MXF (%1)", static_cast<int>(r))));
}
}
int remaining_bits = 0;
/* How many packets in this edit unit (i.e. "frame") */
int packets = 0;
- Fraction const edit_rate = _asset->edit_rate ();
+ auto const edit_rate = _asset->edit_rate ();
if (edit_rate == Fraction(24, 1)) {
edit_rate_code = 0;
remaining_bits = 25;
/*
- Copyright (C) 2012-2020 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2021 Carl Hetherington <cth@carlh.net>
This file is part of libdcp.
files in the program, then also delete it here.
*/
+
/** @file src/sound_asset_writer.h
- * @brief SoundAssetWriter class.
+ * @brief SoundAssetWriter class
*/
+
#include "asset_writer.h"
#include "fsk.h"
#include "types.h"
namespace dcp {
+
class SoundAsset;
+
/** @class SoundAssetWriter
* @brief A helper class for writing to SoundAssets.
*
class SoundAssetWriter : public AssetWriter
{
public:
+ /** @param data Pointer an array of float pointers, one for each channel.
+ * @param frames Number of frames i.e. number of floats that are given for each channel.
+ */
void write (float const * const *, int);
+
bool finalize ();
private:
struct ASDCPState;
std::shared_ptr<ASDCPState> _state;
- SoundAsset* _asset;
- int _frame_buffer_offset;
+ SoundAsset* _asset = nullptr;
+ int _frame_buffer_offset = 0;
/** true to ignore any signal passed to write() on channel 14 and instead write a sync track */
- bool _sync;
+ bool _sync = false;
/** index of the sync packet (0-3) which starts the next edit unit */
- int _sync_packet;
+ int _sync_packet = 0;
FSK _fsk;
std::vector<Channel> _active_channels;
/*
- Copyright (C) 2012-2017 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2021 Carl Hetherington <cth@carlh.net>
This file is part of libdcp.
files in the program, then also delete it here.
*/
+
+/** @file src/sound_frame.cc
+ * @brief SoundFrame class
+ */
+
+
#include "sound_frame.h"
#include <asdcp/AS_DCP.h>
#include <iostream>
+
using std::cout;
using namespace dcp;
+
SoundFrame::SoundFrame (ASDCP::PCM::MXFReader* reader, int n, std::shared_ptr<const DecryptionContext> c)
: Frame<ASDCP::PCM::MXFReader, ASDCP::PCM::FrameBuffer> (reader, n, c)
{
_channels = desc.ChannelCount;
}
+
int32_t
SoundFrame::get (int channel, int frame) const
{
return (d[0] << 8 | (d[1] << 16) | (d[2] << 24)) >> 8;
}
+
int
SoundFrame::channels () const
{
return _channels;
}
+
int
SoundFrame::samples () const
{
/*
- Copyright (C) 2012-2017 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2021 Carl Hetherington <cth@carlh.net>
This file is part of libdcp.
files in the program, then also delete it here.
*/
+
/** @file src/sound_frame.h
- * @brief SoundFrame class.
+ * @brief SoundFrame class
*/
+
#ifndef LIBDCP_SOUND_FRAME_H
#define LIBDCP_SOUND_FRAME_H
+
#include "frame.h"
#include <asdcp/AS_DCP.h>
+
namespace dcp {
+
class SoundFrame : public Frame<ASDCP::PCM::MXFReader, ASDCP::PCM::FrameBuffer>
{
public:
int32_t get (int channel, int sample) const;
private:
- int _channels;
+ int _channels = 0;
};
+
}
+
#endif
/*
- Copyright (C) 2012-2016 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2021 Carl Hetherington <cth@carlh.net>
This file is part of libdcp.
files in the program, then also delete it here.
*/
+
+/** @file src/stereo_picture_asset.cc
+ * @brief StereoPictureAsset class
+ */
+
+
#include "stereo_picture_asset.h"
#include "stereo_picture_frame.h"
#include "exceptions.h"
#include "dcp_assert.h"
#include <asdcp/AS_DCP.h>
+
using std::string;
using std::pair;
using std::make_pair;
using std::dynamic_pointer_cast;
using namespace dcp;
+
StereoPictureAsset::StereoPictureAsset (boost::filesystem::path file)
: PictureAsset (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));
+ auto 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 (ReadError ("could not read video MXF information"));
+ if (ASDCP_FAILURE (reader.FillPictureDescriptor(desc))) {
+ boost::throw_exception (ReadError("could not read video MXF information"));
}
read_picture_descriptor (desc);
ASDCP::WriterInfo info;
- if (ASDCP_FAILURE (reader.FillWriterInfo (info))) {
- boost::throw_exception (ReadError ("could not read video MXF information"));
+ if (ASDCP_FAILURE (reader.FillWriterInfo(info))) {
+ boost::throw_exception (ReadError("could not read video MXF information"));
}
_id = read_writer_info (info);
}
+
StereoPictureAsset::StereoPictureAsset (Fraction edit_rate, Standard standard)
: PictureAsset (edit_rate, standard)
{
}
+
shared_ptr<PictureAssetWriter>
StereoPictureAsset::start_write (boost::filesystem::path file, bool overwrite)
{
- return shared_ptr<StereoPictureAssetWriter> (new StereoPictureAssetWriter (this, file, overwrite));
+ return shared_ptr<StereoPictureAssetWriter> (new StereoPictureAssetWriter(this, file, overwrite));
}
+
shared_ptr<StereoPictureAssetReader>
StereoPictureAsset::start_read () const
{
- return shared_ptr<StereoPictureAssetReader> (new StereoPictureAssetReader (this, key(), standard()));
+ return shared_ptr<StereoPictureAssetReader> (new StereoPictureAssetReader(this, key(), standard()));
}
+
bool
StereoPictureAsset::equals (shared_ptr<const Asset> other, EqualityOptions opt, NoteHandler note) const
{
ASDCP::JP2K::MXFSReader reader_A;
- DCP_ASSERT (file ());
- Kumu::Result_t r = reader_A.OpenRead (file()->string().c_str());
+ DCP_ASSERT (file());
+ auto r = reader_A.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::MXFSReader reader_B;
- DCP_ASSERT (other->file ());
+ DCP_ASSERT (other->file());
r = reader_B.OpenRead (other->file()->string().c_str());
if (ASDCP_FAILURE (r)) {
boost::throw_exception (MXFFileError ("could not open MXF file for reading", other->file()->string(), r));
return false;
}
- shared_ptr<const StereoPictureAsset> other_picture = dynamic_pointer_cast<const StereoPictureAsset> (other);
+ auto other_picture = dynamic_pointer_cast<const StereoPictureAsset> (other);
DCP_ASSERT (other_picture);
- shared_ptr<const StereoPictureAssetReader> reader = start_read ();
- shared_ptr<const StereoPictureAssetReader> other_reader = other_picture->start_read ();
+ auto reader = start_read ();
+ auto other_reader = other_picture->start_read ();
bool result = true;
/*
- Copyright (C) 2012-2015 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2021 Carl Hetherington <cth@carlh.net>
This file is part of libdcp.
files in the program, then also delete it here.
*/
+
+/** @file src/stereo_picture_asset.h
+ * @brief StereoPictureAsset class
+ */
+
+
#ifndef LIBDCP_STEREO_PICTURE_ASSET_H
#define LIBDCP_STEREO_PICTURE_ASSET_H
+
#include "picture_asset.h"
#include "stereo_picture_asset_reader.h"
+
namespace dcp {
-/** A 3D (stereoscopic) picture asset */
+
+/** @class StereoPictureAsset
+ * @brief A 3D (stereoscopic) picture asset
+ */
class StereoPictureAsset : public PictureAsset
{
public:
) const;
};
+
}
+
#endif
/*
- Copyright (C) 2016 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2016-2021 Carl Hetherington <cth@carlh.net>
This file is part of libdcp.
files in the program, then also delete it here.
*/
+
+/** @file src/stereo_picture_asset_reader.h
+ * @brief StereoPictureAssetReader typedef
+ */
+
+
#ifndef LIBDCP_STEREO_PICTURE_ASSET_READER_H
#define LIBDCP_STEREO_PICTURE_ASSET_READER_H
+
#include "asset_reader.h"
#include "stereo_picture_frame.h"
+
namespace dcp {
+
typedef AssetReader<ASDCP::JP2K::MXFSReader, StereoPictureFrame> StereoPictureAssetReader;
+
}
+
#endif
/*
- Copyright (C) 2012-2016 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2021 Carl Hetherington <cth@carlh.net>
This file is part of libdcp.
files in the program, then also delete it here.
*/
+
+/** @file src/stereo_picture_asset_writer.cc
+ * @brief StereoPictureAssetWriter class
+ */
+
+
#include "stereo_picture_asset_writer.h"
#include "exceptions.h"
#include "dcp_assert.h"
#include <asdcp/AS_DCP.h>
#include <asdcp/KM_fileio.h>
+
#include "picture_asset_writer_common.cc"
+
using std::string;
using std::shared_ptr;
using namespace dcp;
+
struct StereoPictureAssetWriter::ASDCPState : public ASDCPStateBase
{
ASDCP::JP2K::MXFSWriter mxf_writer;
};
+
StereoPictureAssetWriter::StereoPictureAssetWriter (PictureAsset* mxf, boost::filesystem::path file, bool overwrite)
: PictureAssetWriter (mxf, file, overwrite)
, _state (new StereoPictureAssetWriter::ASDCPState)
- , _next_eye (Eye::LEFT)
{
}
+
void
StereoPictureAssetWriter::start (uint8_t const * data, int size)
{
_picture_asset->set_frame_rate (Fraction (_picture_asset->edit_rate().numerator * 2, _picture_asset->edit_rate().denominator));
}
-/** Write a frame for one eye. Frames must be written left, then right, then left etc.
- * @param data JPEG2000 data.
- * @param size Size of data.
- */
+
FrameInfo
StereoPictureAssetWriter::write (uint8_t const * data, int size)
{
uint64_t const before_offset = _state->mxf_writer.Tell ();
string hash;
- Kumu::Result_t r = _state->mxf_writer.WriteFrame (
+ auto r = _state->mxf_writer.WriteFrame (
_state->frame_buffer,
_next_eye == Eye::LEFT ? ASDCP::JP2K::SP_LEFT : ASDCP::JP2K::SP_RIGHT,
_crypto_context->context(),
return FrameInfo (before_offset, _state->mxf_writer.Tell() - before_offset, hash);
}
+
void
StereoPictureAssetWriter::fake_write (int size)
{
DCP_ASSERT (_started);
DCP_ASSERT (!_finalized);
- Kumu::Result_t r = _state->mxf_writer.FakeWriteFrame (size, _next_eye == Eye::LEFT ? ASDCP::JP2K::SP_LEFT : ASDCP::JP2K::SP_RIGHT);
- if (ASDCP_FAILURE (r)) {
- boost::throw_exception (MXFFileError ("error in writing video MXF", _file.string(), r));
+ auto r = _state->mxf_writer.FakeWriteFrame (size, _next_eye == Eye::LEFT ? ASDCP::JP2K::SP_LEFT : ASDCP::JP2K::SP_RIGHT);
+ if (ASDCP_FAILURE(r)) {
+ boost::throw_exception (MXFFileError("error in writing video MXF", _file.string(), r));
}
_next_eye = _next_eye == Eye::LEFT ? Eye::RIGHT : Eye::LEFT;
}
}
+
bool
StereoPictureAssetWriter::finalize ()
{
if (_started) {
- Kumu::Result_t r = _state->mxf_writer.Finalize();
- if (ASDCP_FAILURE (r)) {
- boost::throw_exception (MXFFileError ("error in finalizing video MXF", _file.string(), r));
+ auto r = _state->mxf_writer.Finalize();
+ if (ASDCP_FAILURE(r)) {
+ boost::throw_exception (MXFFileError("error in finalizing video MXF", _file.string(), r));
}
}
/*
- Copyright (C) 2012-2016 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2021 Carl Hetherington <cth@carlh.net>
This file is part of libdcp.
files in the program, then also delete it here.
*/
+
+/** @file src/stereo_picture_asset_writer.h
+ * @brief StereoPictureAssetWriter class
+ */
+
+
#include "picture_asset_writer.h"
#include "types.h"
#include <memory>
-#include <boost/utility.hpp>
#include <stdint.h>
#include <string>
-#include <fstream>
+
namespace dcp {
+
/** @class StereoPictureAssetWriter
* @brief A helper class for writing to StereoPictureAssets.
*
struct ASDCPState;
std::shared_ptr<ASDCPState> _state;
- dcp::Eye _next_eye;
+ dcp::Eye _next_eye = Eye::LEFT;
};
+
}
/*
- Copyright (C) 2012-2018 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2021 Carl Hetherington <cth@carlh.net>
This file is part of libdcp.
files in the program, then also delete it here.
*/
+
+/** @file src/subtitle.cc
+ * @brief Subtitle class
+ */
+
+
#include "subtitle.h"
#include "dcp_time.h"
+
using namespace dcp;
+
/** @param v_position Vertical position as a fraction of the screen height (between 0 and 1) from v_align */
Subtitle::Subtitle (
Time in,
files in the program, then also delete it here.
*/
+
#ifndef LIBDCP_SUBTITLE_H
#define LIBDCP_SUBTITLE_H
+
/** @file src/subtitle.h
- * @brief Subtitle class.
+ * @brief Subtitle class
*/
+
#include "dcp_time.h"
+
namespace dcp {
+
class Subtitle
{
public:
/** Horizontal position as a proportion of the screen width from the _h_align
* (between 0 and 1)
*/
- float _h_position;
- HAlign _h_align;
+ float _h_position = 0;
+ HAlign _h_align = HAlign::CENTER;
/** Vertical position as a proportion of the screen height from the _v_align
* (between 0 and 1)
*/
- float _v_position;
- VAlign _v_align;
+ float _v_position = 0;
+ VAlign _v_align = VAlign::CENTER;
Time _fade_up_time;
Time _fade_down_time;
};
+
}
+
#endif
files in the program, then also delete it here.
*/
+
+/** @file src/subtitle_asset.cc
+ * @brief SubtitleAsset class
+ */
+
+
#include "raw_convert.h"
#include "compose.hpp"
#include "subtitle_asset.h"
#include <boost/lexical_cast.hpp>
#include <boost/shared_array.hpp>
+
using std::dynamic_pointer_cast;
using std::string;
using std::cout;
using boost::lexical_cast;
using namespace dcp;
+
SubtitleAsset::SubtitleAsset ()
{
}
+
SubtitleAsset::SubtitleAsset (boost::filesystem::path file)
: Asset (file)
{
}
+
string
string_attribute (xmlpp::Element const * node, string name)
{
- xmlpp::Attribute* a = node->get_attribute (name);
+ auto a = node->get_attribute (name);
if (!a) {
throw XMLError (String::compose ("missing attribute %1", name));
}
return string (a->get_value ());
}
+
optional<string>
optional_string_attribute (xmlpp::Element const * node, string name)
{
- xmlpp::Attribute* a = node->get_attribute (name);
+ auto a = node->get_attribute (name);
if (!a) {
- return optional<string>();
+ return {};
}
return string (a->get_value ());
}
+
optional<bool>
optional_bool_attribute (xmlpp::Element const * node, string name)
{
- optional<string> s = optional_string_attribute (node, name);
+ auto s = optional_string_attribute (node, name);
if (!s) {
- return optional<bool> ();
+ return {};
}
return (s.get() == "1" || s.get() == "yes");
}
+
template <class T>
optional<T>
optional_number_attribute (xmlpp::Element const * node, string name)
{
- boost::optional<std::string> s = optional_string_attribute (node, name);
+ auto s = optional_string_attribute (node, name);
if (!s) {
return boost::optional<T> ();
}
return raw_convert<T> (t);
}
+
SubtitleAsset::ParseState
SubtitleAsset::font_node_state (xmlpp::Element const * node, Standard standard) const
{
} else {
ps.underline = optional_bool_attribute (node, "Underline");
}
- optional<string> c = optional_string_attribute (node, "Color");
+ auto c = optional_string_attribute (node, "Color");
if (c) {
ps.colour = Colour (c.get ());
}
- optional<string> const e = optional_string_attribute (node, "Effect");
+ auto const e = optional_string_attribute (node, "Effect");
if (e) {
ps.effect = string_to_effect (e.get ());
}
void
SubtitleAsset::position_align (SubtitleAsset::ParseState& ps, xmlpp::Element const * node) const
{
- optional<float> hp = optional_number_attribute<float> (node, "HPosition");
+ auto hp = optional_number_attribute<float> (node, "HPosition");
if (!hp) {
hp = optional_number_attribute<float> (node, "Hposition");
}
ps.h_position = hp.get () / 100;
}
- optional<string> ha = optional_string_attribute (node, "HAlign");
+ auto ha = optional_string_attribute (node, "HAlign");
if (!ha) {
ha = optional_string_attribute (node, "Halign");
}
ps.h_align = string_to_halign (ha.get ());
}
- optional<float> vp = optional_number_attribute<float> (node, "VPosition");
+ auto vp = optional_number_attribute<float> (node, "VPosition");
if (!vp) {
vp = optional_number_attribute<float> (node, "Vposition");
}
ps.v_position = vp.get () / 100;
}
- optional<string> va = optional_string_attribute (node, "VAlign");
+ auto va = optional_string_attribute (node, "VAlign");
if (!va) {
va = optional_string_attribute (node, "Valign");
}
}
+
SubtitleAsset::ParseState
SubtitleAsset::text_node_state (xmlpp::Element const * node) const
{
position_align (ps, node);
- optional<string> d = optional_string_attribute (node, "Direction");
+ auto d = optional_string_attribute (node, "Direction");
if (d) {
ps.direction = string_to_direction (d.get ());
}
return ps;
}
+
SubtitleAsset::ParseState
SubtitleAsset::image_node_state (xmlpp::Element const * node) const
{
return ps;
}
+
SubtitleAsset::ParseState
SubtitleAsset::subtitle_node_state (xmlpp::Element const * node, optional<int> tcr) const
{
return ps;
}
+
Time
SubtitleAsset::fade_time (xmlpp::Element const * node, string name, optional<int> tcr) const
{
- string const u = optional_string_attribute(node, name).get_value_or ("");
+ auto const u = optional_string_attribute(node, name).get_value_or ("");
Time t;
if (u.empty ()) {
return t;
}
+
void
SubtitleAsset::parse_subtitles (xmlpp::Element const * node, vector<ParseState>& state, optional<int> tcr, Standard standard)
{
throw XMLError ("unexpected node " + node->get_name());
}
- xmlpp::Node::NodeList c = node->get_children ();
- for (xmlpp::Node::NodeList::const_iterator i = c.begin(); i != c.end(); ++i) {
- xmlpp::ContentNode const * v = dynamic_cast<xmlpp::ContentNode const *> (*i);
+ for (auto i: node->get_children()) {
+ auto const v = dynamic_cast<xmlpp::ContentNode const *>(i);
if (v) {
maybe_add_subtitle (v->get_content(), state, standard);
}
- xmlpp::Element const * e = dynamic_cast<xmlpp::Element const *> (*i);
+ auto const e = dynamic_cast<xmlpp::Element const *>(i);
if (e) {
parse_subtitles (e, state, tcr, standard);
}
state.pop_back ();
}
+
void
SubtitleAsset::maybe_add_subtitle (string text, vector<ParseState> const & parse_state, Standard standard)
{
switch (ps.type.get()) {
case ParseState::Type::TEXT:
_subtitles.push_back (
- shared_ptr<Subtitle> (
- new SubtitleString (
- ps.font_id,
- ps.italic.get_value_or (false),
- ps.bold.get_value_or (false),
- ps.underline.get_value_or (false),
- ps.colour.get_value_or (dcp::Colour (255, 255, 255)),
- ps.size.get_value_or (42),
- ps.aspect_adjust.get_value_or (1.0),
- ps.in.get(),
- ps.out.get(),
- ps.h_position.get_value_or(0),
- ps.h_align.get_value_or(HAlign::CENTER),
- ps.v_position.get_value_or(0),
- ps.v_align.get_value_or(VAlign::CENTER),
- ps.direction.get_value_or (Direction::LTR),
- text,
- ps.effect.get_value_or (Effect::NONE),
- ps.effect_colour.get_value_or (dcp::Colour (0, 0, 0)),
- ps.fade_up_time.get_value_or(Time()),
- ps.fade_down_time.get_value_or(Time())
- )
+ make_shared<SubtitleString>(
+ ps.font_id,
+ ps.italic.get_value_or (false),
+ ps.bold.get_value_or (false),
+ ps.underline.get_value_or (false),
+ ps.colour.get_value_or (dcp::Colour (255, 255, 255)),
+ ps.size.get_value_or (42),
+ ps.aspect_adjust.get_value_or (1.0),
+ ps.in.get(),
+ ps.out.get(),
+ ps.h_position.get_value_or(0),
+ ps.h_align.get_value_or(HAlign::CENTER),
+ ps.v_position.get_value_or(0),
+ ps.v_align.get_value_or(VAlign::CENTER),
+ ps.direction.get_value_or (Direction::LTR),
+ text,
+ ps.effect.get_value_or (Effect::NONE),
+ ps.effect_colour.get_value_or (dcp::Colour (0, 0, 0)),
+ ps.fade_up_time.get_value_or(Time()),
+ ps.fade_down_time.get_value_or(Time())
)
);
break;
case ParseState::Type::IMAGE:
/* Add a subtitle with no image data and we'll fill that in later */
_subtitles.push_back (
- shared_ptr<Subtitle> (
- new SubtitleImage (
- ArrayData (),
- standard == Standard::INTEROP ? text.substr(0, text.size() - 4) : text,
- ps.in.get(),
- ps.out.get(),
- ps.h_position.get_value_or(0),
- ps.h_align.get_value_or(HAlign::CENTER),
- ps.v_position.get_value_or(0),
- ps.v_align.get_value_or(VAlign::CENTER),
- ps.fade_up_time.get_value_or(Time()),
- ps.fade_down_time.get_value_or(Time())
- )
+ make_shared<SubtitleImage>(
+ ArrayData(),
+ standard == Standard::INTEROP ? text.substr(0, text.size() - 4) : text,
+ ps.in.get(),
+ ps.out.get(),
+ ps.h_position.get_value_or(0),
+ ps.h_align.get_value_or(HAlign::CENTER),
+ ps.v_position.get_value_or(0),
+ ps.v_align.get_value_or(VAlign::CENTER),
+ ps.fade_up_time.get_value_or(Time()),
+ ps.fade_down_time.get_value_or(Time())
)
);
break;
_subtitles.push_back (s);
}
+
Time
SubtitleAsset::latest_subtitle_out () const
{
return t;
}
+
bool
SubtitleAsset::equals (shared_ptr<const Asset> other_asset, EqualityOptions options, NoteHandler note) const
{
auto j = other->_subtitles.begin();
while (i != _subtitles.end()) {
- shared_ptr<SubtitleString> string_i = dynamic_pointer_cast<SubtitleString> (*i);
- shared_ptr<SubtitleString> string_j = dynamic_pointer_cast<SubtitleString> (*j);
- shared_ptr<SubtitleImage> image_i = dynamic_pointer_cast<SubtitleImage> (*i);
- shared_ptr<SubtitleImage> image_j = dynamic_pointer_cast<SubtitleImage> (*j);
+ auto string_i = dynamic_pointer_cast<SubtitleString> (*i);
+ auto string_j = dynamic_pointer_cast<SubtitleString> (*j);
+ auto image_i = dynamic_pointer_cast<SubtitleImage> (*i);
+ auto image_j = dynamic_pointer_cast<SubtitleImage> (*j);
if ((string_i && !string_j) || (image_i && !image_j)) {
note (NoteType::ERROR, "subtitles differ: string vs. image");
return true;
}
+
struct SubtitleSorter
{
bool operator() (shared_ptr<Subtitle> a, shared_ptr<Subtitle> b) {
}
};
+
void
SubtitleAsset::pull_fonts (shared_ptr<order::Part> part)
{
part->children = merged;
}
+
/** @param standard Standard (INTEROP or SMPTE); this is used rather than putting things in the child
* class because the differences between the two are fairly subtle.
*/
text->children.push_back (shared_ptr<order::String> (new order::String (text, order::Font (is, standard), is->text())));
}
- shared_ptr<SubtitleImage> ii = dynamic_pointer_cast<SubtitleImage>(i);
+ auto ii = dynamic_pointer_cast<SubtitleImage>(i);
if (ii) {
text.reset ();
subtitle->children.push_back (
root->write_xml (xml_root, context);
}
+
map<string, ArrayData>
SubtitleAsset::font_data () const
{
/*
- Copyright (C) 2012-2015 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2021 Carl Hetherington <cth@carlh.net>
This file is part of libdcp.
files in the program, then also delete it here.
*/
+
+/** @file src/subtitle_asset.h
+ * @brief SubtitleAsset class
+ */
+
+
#ifndef LIBDCP_SUBTITLE_ASSET_H
#define LIBDCP_SUBTITLE_ASSET_H
#include <boost/shared_array.hpp>
#include <map>
+
namespace xmlpp {
class Element;
}
+
struct interop_dcp_font_test;
struct smpte_dcp_font_test;
struct pull_fonts_test1;
struct pull_fonts_test2;
struct pull_fonts_test3;
-namespace dcp
-{
+
+namespace dcp {
+
class SubtitleString;
class SubtitleImage;
class LoadFontNode;
class ReelAsset;
+
namespace order {
class Part;
struct Context;
}
+
/** @class SubtitleAsset
- * @brief A parent for classes representing a file containing subtitles.
+ * @brief A parent for classes representing a file containing subtitles
*
* This class holds a list of Subtitle objects which it can extract
* from the appropriate part of either an Interop or SMPTE XML file.
static void pull_fonts (std::shared_ptr<order::Part> part);
};
+
}
+
#endif
/*
- Copyright (C) 2012-2018 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2021 Carl Hetherington <cth@carlh.net>
This file is part of libdcp.
files in the program, then also delete it here.
*/
+
+/** @file src/subtitle_asset_internal.cc
+ * @brief Internal SubtitleAsset helpers
+ */
+
+
#include "subtitle_asset_internal.h"
#include "subtitle_string.h"
#include "compose.hpp"
#include <cmath>
+
using std::string;
using std::map;
using std::shared_ptr;
using namespace dcp;
+
string
order::Context::xmlns () const
{
return standard == Standard::SMPTE ? "dcst" : "";
}
+
order::Font::Font (shared_ptr<SubtitleString> s, Standard standard)
{
if (s->font()) {
_values["Weight"] = s->bold() ? "bold" : "normal";
}
+
xmlpp::Element*
order::Font::as_xml (xmlpp::Element* parent, Context& context) const
{
return e;
}
+
/** Modify our values so that they contain only those that are common to us and
* other.
*/
{
map<string, string> inter;
- for (map<string, string>::const_iterator i = other._values.begin(); i != other._values.end(); ++i) {
- map<string, string>::iterator t = _values.find (i->first);
- if (t != _values.end() && t->second == i->second) {
- inter.insert (*i);
+ for (auto const& i: other._values) {
+ auto t = _values.find (i.first);
+ if (t != _values.end() && t->second == i.second) {
+ inter.insert (i);
}
}
_values = inter;
}
+
/** Modify our values so that it contains only those keys that are not in other */
void
order::Font::take_difference (Font other)
{
map<string, string> diff;
- for (map<string, string>::const_iterator i = _values.begin(); i != _values.end(); ++i) {
- if (other._values.find (i->first) == other._values.end ()) {
- diff.insert (*i);
+ for (auto const& i: _values) {
+ if (other._values.find (i.first) == other._values.end()) {
+ diff.insert (i);
}
}
_values = diff;
}
+
bool
order::Font::empty () const
{
return _values.empty ();
}
+
xmlpp::Element*
order::Part::as_xml (xmlpp::Element* parent, Context &) const
{
return parent;
}
+
xmlpp::Element*
order::String::as_xml (xmlpp::Element* parent, Context &) const
{
return 0;
}
+
void
order::Part::write_xml (xmlpp::Element* parent, order::Context& context) const
{
}
}
+
static void
position_align (xmlpp::Element* e, order::Context& context, HAlign h_align, float h_position, VAlign v_align, float v_position)
{
}
}
+
xmlpp::Element*
order::Text::as_xml (xmlpp::Element* parent, Context& context) const
{
- xmlpp::Element* e = parent->add_child ("Text", context.xmlns());
+ auto e = parent->add_child ("Text", context.xmlns());
position_align (e, context, _h_align, _h_position, _v_align, _v_position);
return e;
}
+
xmlpp::Element*
order::Subtitle::as_xml (xmlpp::Element* parent, Context& context) const
{
- xmlpp::Element* e = parent->add_child ("Subtitle", context.xmlns());
+ auto e = parent->add_child ("Subtitle", context.xmlns());
e->set_attribute ("SpotNumber", raw_convert<string> (context.spot_number++));
e->set_attribute ("TimeIn", _in.rebase(context.time_code_rate).as_string(context.standard));
e->set_attribute ("TimeOut", _out.rebase(context.time_code_rate).as_string(context.standard));
return e;
}
+
bool
order::Font::operator== (Font const & other) const
{
return _values == other._values;
}
+
void
order::Font::clear ()
{
_values.clear ();
}
+
xmlpp::Element *
order::Image::as_xml (xmlpp::Element* parent, Context& context) const
{
- xmlpp::Element* e = parent->add_child ("Image", context.xmlns());
+ auto e = parent->add_child ("Image", context.xmlns());
position_align (e, context, _h_align, _h_position, _v_align, _v_position);
if (context.standard == Standard::SMPTE) {
/*
- Copyright (C) 2012-2016 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2021 Carl Hetherington <cth@carlh.net>
This file is part of libdcp.
files in the program, then also delete it here.
*/
+
+/** @file src/subtitle_asset_internal.h
+ * @brief Internal SubtitleAsset helpers
+ */
+
+
#ifndef LIBDCP_SUBTITLE_ASSET_INTERNAL_H
#define LIBDCP_SUBTITLE_ASSET_INTERNAL_H
#include "dcp_time.h"
#include <libxml++/libxml++.h>
+
struct take_intersection_test;
struct take_difference_test;
struct pull_fonts_test1;
struct pull_fonts_test2;
struct pull_fonts_test3;
+
namespace dcp {
+
class SubtitleString;
+
namespace order {
+
struct Context
{
std::string xmlns () const;
int spot_number;
};
+
class Font
{
public:
std::map<std::string, std::string> _values;
};
+
class Part
{
public:
std::vector<std::shared_ptr<Part>> children;
};
+
class String : public Part
{
public:
std::string text;
};
+
class Text : public Part
{
public:
Direction _direction;
};
+
class Subtitle : public Part
{
public:
Time _fade_down;
};
+
class Image : public Part
{
public:
float _v_position;
};
-}
}
+}
+
#endif