diff options
| author | Carl Hetherington <cth@carlh.net> | 2021-01-24 04:15:26 +0100 |
|---|---|---|
| committer | Carl Hetherington <cth@carlh.net> | 2021-01-24 04:15:26 +0100 |
| commit | ceaf7bc52712cb60708ed5eb5c62c5e463dd8e89 (patch) | |
| tree | c55e4b85ee30138ce83263045d77d01631378b2e /src | |
| parent | 6c37cc1979b2a01205a888c4c98f3334685ee8dd (diff) | |
Tidying.
Diffstat (limited to 'src')
130 files changed, 1930 insertions, 758 deletions
diff --git a/src/array_data.cc b/src/array_data.cc index 61e79395..2df53830 100644 --- a/src/array_data.cc +++ b/src/array_data.cc @@ -32,6 +32,11 @@ */ +/** @file src/array_data.cc + * @brief ArrayData class + */ + + #include "array_data.h" #include "util.h" #include "exceptions.h" @@ -44,7 +49,6 @@ using namespace dcp; ArrayData::ArrayData () - : _size (0) { } diff --git a/src/array_data.h b/src/array_data.h index 8c2f6d55..69962bf2 100644 --- a/src/array_data.h +++ b/src/array_data.h @@ -94,7 +94,7 @@ public: private: boost::shared_array<uint8_t> _data; /** amount of `valid' data in _data; the array may be larger */ - int _size; + int _size = 0; }; diff --git a/src/asset_reader.h b/src/asset_reader.h index 859c88f3..2da67bd8 100644 --- a/src/asset_reader.h +++ b/src/asset_reader.h @@ -32,6 +32,11 @@ */ +/** @file src/asset_reader.h + * @brief AssetReader class + */ + + #ifndef LIBDCP_ASSET_READER_H #define LIBDCP_ASSET_READER_H @@ -46,22 +51,16 @@ 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; @@ -72,6 +71,7 @@ public: 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)); } @@ -82,6 +82,24 @@ public: 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)); + } + } }; diff --git a/src/asset_writer.cc b/src/asset_writer.cc index 73fc2046..05d0aa23 100644 --- a/src/asset_writer.cc +++ b/src/asset_writer.cc @@ -33,7 +33,7 @@ /** @file src/asset_writer.h - * @brief AssetWriter class. + * @brief AssetWriter class */ @@ -61,7 +61,6 @@ AssetWriter::AssetWriter (MXF* mxf, boost::filesystem::path file) } -/** @return true if anything was written by this writer */ bool AssetWriter::finalize () { diff --git a/src/asset_writer.h b/src/asset_writer.h index 7eecc03f..c1fc1900 100644 --- a/src/asset_writer.h +++ b/src/asset_writer.h @@ -33,7 +33,7 @@ /** @file src/asset_writer.h - * @brief AssetWriter class. + * @brief AssetWriter class */ @@ -65,6 +65,8 @@ public: AssetWriter& operator= (AssetWriter const&) = delete; virtual ~AssetWriter () {} + + /** @return true if anything was written by this writer */ virtual bool finalize (); int64_t frames_written () const { diff --git a/src/atmos_asset.cc b/src/atmos_asset.cc index b8743092..ae381737 100644 --- a/src/atmos_asset.cc +++ b/src/atmos_asset.cc @@ -32,6 +32,11 @@ */ +/** @file src/atmos_asset.cc + * @brief AtmosAsset class + */ + + #include "atmos_asset.h" #include "atmos_asset_reader.h" #include "atmos_asset_writer.h" @@ -48,7 +53,6 @@ using namespace dcp; 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) @@ -105,7 +109,8 @@ AtmosAsset::static_pkl_type (Standard) 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)); } diff --git a/src/atmos_asset.h b/src/atmos_asset.h index 817bc975..7ee55d92 100644 --- a/src/atmos_asset.h +++ b/src/atmos_asset.h @@ -104,12 +104,12 @@ private: 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; }; diff --git a/src/atmos_asset_reader.h b/src/atmos_asset_reader.h index 14806261..2a24b832 100644 --- a/src/atmos_asset_reader.h +++ b/src/atmos_asset_reader.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2016 Carl Hetherington <cth@carlh.net> + Copyright (C) 2016-2021 Carl Hetherington <cth@carlh.net> This file is part of libdcp. @@ -31,11 +31,20 @@ 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; + } diff --git a/src/atmos_asset_writer.cc b/src/atmos_asset_writer.cc index 891a8c01..957bd4cb 100644 --- a/src/atmos_asset_writer.cc +++ b/src/atmos_asset_writer.cc @@ -32,6 +32,11 @@ */ +/** @file src/atmos_asset_writer.cc + * @brief AtmosAssetWriter class + */ + + #include "atmos_asset_writer.h" #include "atmos_asset.h" #include "exceptions.h" @@ -110,6 +115,7 @@ AtmosAssetWriter::write (uint8_t const * data, int size) ++_frames_written; } + bool AtmosAssetWriter::finalize () { diff --git a/src/atmos_frame.h b/src/atmos_frame.h index 763875bd..0ea60c23 100644 --- a/src/atmos_frame.h +++ b/src/atmos_frame.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2016 Carl Hetherington <cth@carlh.net> + Copyright (C) 2016-2021 Carl Hetherington <cth@carlh.net> This file is part of libdcp. @@ -31,19 +31,26 @@ 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 diff --git a/src/bitstream.cc b/src/bitstream.cc index 13d5ae4b..8b7988dd 100644 --- a/src/bitstream.cc +++ b/src/bitstream.cc @@ -1,5 +1,5 @@ /* - Copyright (C) 2020 Carl Hetherington <cth@carlh.net> + Copyright (C) 2020-2021 Carl Hetherington <cth@carlh.net> This file is part of libdcp. @@ -32,6 +32,11 @@ */ +/** @file src/bitstream.cc + * @brief Bitstream class + */ + + #include "bitstream.h" #include "dcp_assert.h" #include <iostream> diff --git a/src/bitstream.h b/src/bitstream.h index 1295f79e..2dc7c20e 100644 --- a/src/bitstream.h +++ b/src/bitstream.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2020 Carl Hetherington <cth@carlh.net> + Copyright (C) 2020-2021 Carl Hetherington <cth@carlh.net> This file is part of libdcp. @@ -32,6 +32,11 @@ */ +/** @file src/bitstream.h + * @brief Bitstream class + */ + + #include <boost/crc.hpp> #include <boost/optional.hpp> #include <stdint.h> @@ -40,6 +45,7 @@ namespace dcp { + class Bitstream { public: @@ -58,4 +64,5 @@ private: boost::optional<boost::crc_basic<16> > _crc; }; + } diff --git a/src/certificate.cc b/src/certificate.cc index b285df5f..93f271ef 100644 --- a/src/certificate.cc +++ b/src/certificate.cc @@ -33,7 +33,7 @@ /** @file src/certificate.cc - * @brief Certificate class. + * @brief Certificate class */ diff --git a/src/certificate.h b/src/certificate.h index 7a8c2a44..1b8188c7 100644 --- a/src/certificate.h +++ b/src/certificate.h @@ -33,7 +33,7 @@ /** @file src/certificate.h - * @brief Certificate class. + * @brief Certificate class */ @@ -139,4 +139,5 @@ std::ostream& operator<< (std::ostream&s, Certificate const & c); } + #endif diff --git a/src/chromaticity.cc b/src/chromaticity.cc index 9d67d72f..ca96c011 100644 --- a/src/chromaticity.cc +++ b/src/chromaticity.cc @@ -1,5 +1,5 @@ /* - Copyright (C) 2016 Carl Hetherington <cth@carlh.net> + Copyright (C) 2016-2021 Carl Hetherington <cth@carlh.net> This file is part of libdcp. @@ -31,10 +31,18 @@ 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 () { diff --git a/src/chromaticity.h b/src/chromaticity.h index c62731f7..41bb8fda 100644 --- a/src/chromaticity.h +++ b/src/chromaticity.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2015 Carl Hetherington <cth@carlh.net> + Copyright (C) 2015-2021 Carl Hetherington <cth@carlh.net> This file is part of libdcp. @@ -31,35 +31,37 @@ 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; @@ -67,12 +69,14 @@ public: /** @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 diff --git a/src/colour_conversion.cc b/src/colour_conversion.cc index 1251d94f..84218d87 100644 --- a/src/colour_conversion.cc +++ b/src/colour_conversion.cc @@ -31,6 +31,12 @@ 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" @@ -41,15 +47,17 @@ #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), @@ -65,7 +73,7 @@ ColourConversion::srgb_to_xyz () 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), @@ -81,7 +89,7 @@ ColourConversion::rec601_to_xyz () 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), @@ -97,7 +105,7 @@ ColourConversion::rec709_to_xyz () 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), @@ -116,7 +124,7 @@ ColourConversion::rec1886_to_xyz () /* According to Olivier on DCP-o-matic bug #832, Rec. 1886 is Rec. 709 with 2.4 gamma, so here goes ... */ - static ColourConversion* c = new ColourConversion ( + static auto c = new ColourConversion ( make_shared<GammaTransferFunction>(2.4), YUVToRGB::REC709, Chromaticity (0.64, 0.33), @@ -132,7 +140,7 @@ ColourConversion::rec1886_to_xyz () 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), @@ -149,7 +157,7 @@ ColourConversion::rec2020_to_xyz () 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), @@ -186,6 +194,7 @@ ColourConversion::ColourConversion ( } + bool ColourConversion::about_equal (ColourConversion const & other, float epsilon) const { @@ -217,6 +226,7 @@ ColourConversion::about_equal (ColourConversion const & other, float epsilon) co return false; } + boost::numeric::ublas::matrix<double> ColourConversion::rgb_to_xyz () const { @@ -240,13 +250,14 @@ 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); @@ -254,7 +265,7 @@ ColourConversion::xyz_to_rgb () const /* 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); @@ -262,6 +273,7 @@ ColourConversion::xyz_to_rgb () const return xyz_to_rgb; } + boost::numeric::ublas::matrix<double> ColourConversion::bradford () const { diff --git a/src/colour_conversion.h b/src/colour_conversion.h index d613c143..83ba3ad3 100644 --- a/src/colour_conversion.h +++ b/src/colour_conversion.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2014-2015 Carl Hetherington <cth@carlh.net> + Copyright (C) 2014-2021 Carl Hetherington <cth@carlh.net> This file is part of libdcp. @@ -31,13 +31,16 @@ 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 @@ -46,19 +49,23 @@ #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 { @@ -175,6 +182,8 @@ protected: std::shared_ptr<const TransferFunction> _out; }; + } + #endif diff --git a/src/combine.cc b/src/combine.cc index c2cae547..dd8a145c 100644 --- a/src/combine.cc +++ b/src/combine.cc @@ -32,6 +32,11 @@ */ +/** @file src/combine.cc + * @brief Method to combine DCPs + */ + + #include "asset.h" #include "combine.h" #include "cpl.h" @@ -135,27 +140,27 @@ dcp::combine ( 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); diff --git a/src/combine.h b/src/combine.h index 21acbb04..dd992f1b 100644 --- a/src/combine.h +++ b/src/combine.h @@ -32,6 +32,11 @@ */ +/** @file src/combine.h + * @brief Method to combine DCPs + */ + + #include "compose.hpp" #include "version.h" #include <boost/filesystem.hpp> @@ -39,8 +44,10 @@ namespace dcp { + class CertificateChain; + void combine ( std::vector<boost::filesystem::path> inputs, boost::filesystem::path output, @@ -51,5 +58,6 @@ void combine ( std::shared_ptr<const CertificateChain> signer = std::shared_ptr<CertificateChain>() ); + } @@ -31,6 +31,12 @@ 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" @@ -51,6 +57,7 @@ #include <libxml++/libxml++.h> #include <boost/algorithm/string.hpp> + using std::string; using std::list; using std::pair; @@ -86,7 +93,7 @@ CPL::CPL (string annotation_text, ContentKind content_kind) _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) @@ -143,7 +150,6 @@ CPL::CPL (boost::filesystem::path file) } } - f.ignore_child ("Issuer"); f.ignore_child ("Signer"); f.ignore_child ("Signature"); @@ -151,21 +157,14 @@ CPL::CPL (boost::filesystem::path file) 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 { @@ -544,6 +543,7 @@ CPL::reel_mxfs () const return c; } + bool CPL::equals (shared_ptr<const Asset> other, EqualityOptions opt, NoteHandler note) const { @@ -582,7 +582,7 @@ CPL::equals (shared_ptr<const Asset> other, EqualityOptions opt, NoteHandler not return true; } -/** @return true if we have any encrypted content */ + bool CPL::any_encrypted () const { @@ -596,7 +596,6 @@ CPL::any_encrypted () const } -/** @return true if we have all our encryptable content is encrypted */ bool CPL::all_encrypted () const { @@ -610,10 +609,6 @@ 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) { @@ -67,12 +67,14 @@ class DecryptedKDM; /** @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 ( @@ -81,7 +83,15 @@ public: 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 */ @@ -93,9 +103,18 @@ public: 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, diff --git a/src/crypto_context.h b/src/crypto_context.h index 263121bf..6020ea88 100644 --- a/src/crypto_context.h +++ b/src/crypto_context.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2012-2018 Carl Hetherington <cth@carlh.net> + Copyright (C) 2012-2021 Carl Hetherington <cth@carlh.net> This file is part of libdcp. @@ -31,9 +31,16 @@ 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" @@ -41,22 +48,24 @@ #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"); } @@ -76,7 +85,7 @@ public: 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"); } } @@ -100,9 +109,12 @@ private: ASDCP::HMACContext* _hmac; }; + typedef CryptoContext<ASDCP::AESEncContext> EncryptionContext; typedef CryptoContext<ASDCP::AESDecContext> DecryptionContext; + } + #endif diff --git a/src/data.cc b/src/data.cc index 23e62573..79f58f93 100644 --- a/src/data.cc +++ b/src/data.cc @@ -1,5 +1,5 @@ /* - Copyright (C) 2015-2020 Carl Hetherington <cth@carlh.net> + Copyright (C) 2015-2021 Carl Hetherington <cth@carlh.net> This file is part of libdcp. @@ -32,9 +32,14 @@ */ +/** @file src/data.cc + * @brief Data class + */ + + #include "data.h" -#include "util.h" #include "exceptions.h" +#include "util.h" #include <cstdio> #include <cerrno> @@ -45,16 +50,15 @@ using namespace dcp; 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); } @@ -32,6 +32,11 @@ */ +/** @file src/data.h + * @brief Data class + */ + + #ifndef LIBDCP_DATA_H #define LIBDCP_DATA_H @@ -63,4 +68,5 @@ bool operator!=(Data const & a, Data const & b); } + #endif @@ -31,10 +31,12 @@ 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" @@ -307,7 +309,7 @@ DCP::equals (DCP const & other, EqualityOptions opt, NoteHandler note) const void -DCP::add (std::shared_ptr<CPL> cpl) +DCP::add (shared_ptr<CPL> cpl) { _cpls.push_back (cpl); } @@ -33,7 +33,7 @@ /** @file src/dcp.h - * @brief DCP class. + * @brief DCP class */ diff --git a/src/dcp_assert.h b/src/dcp_assert.h index d8bf20e6..773739b7 100644 --- a/src/dcp_assert.h +++ b/src/dcp_assert.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2014 Carl Hetherington <cth@carlh.net> + Copyright (C) 2014-2021 Carl Hetherington <cth@carlh.net> This file is part of libdcp. @@ -31,6 +31,13 @@ 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__); diff --git a/src/dcp_time.cc b/src/dcp_time.cc index 7a4a67d6..2895cd37 100644 --- a/src/dcp_time.cc +++ b/src/dcp_time.cc @@ -1,5 +1,5 @@ /* - Copyright (C) 2012-2016 Carl Hetherington <cth@carlh.net> + Copyright (C) 2012-2021 Carl Hetherington <cth@carlh.net> This file is part of libdcp. @@ -31,10 +31,12 @@ 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" @@ -46,25 +48,24 @@ #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. * @@ -94,14 +95,7 @@ Time::set (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::Time (string time, optional<int> tcr_) { vector<string> b; @@ -170,30 +164,35 @@ Time::Time (string time, optional<int> tcr_) } } + 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) { @@ -212,6 +211,7 @@ 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) { @@ -230,6 +230,7 @@ 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) { @@ -237,6 +238,7 @@ dcp::operator<< (ostream& s, Time const & t) return s; } + dcp::Time dcp::operator+ (Time a, Time b) { @@ -274,6 +276,7 @@ dcp::operator+ (Time a, Time b) return r; } + dcp::Time dcp::operator- (Time a, Time b) { @@ -311,6 +314,7 @@ dcp::operator- (Time a, Time b) return r; } + float dcp::operator/ (Time a, Time const & b) { @@ -319,7 +323,7 @@ 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 { @@ -334,26 +338,21 @@ 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 { diff --git a/src/dcp_time.h b/src/dcp_time.h index 9320d8ba..997b8d13 100644 --- a/src/dcp_time.h +++ b/src/dcp_time.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2012-2015 Carl Hetherington <cth@carlh.net> + Copyright (C) 2012-2021 Carl Hetherington <cth@carlh.net> This file is part of libdcp. @@ -31,23 +31,29 @@ 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); @@ -59,6 +65,7 @@ extern Time operator+ (Time a, Time 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. */ @@ -66,7 +73,7 @@ class Time { 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). @@ -90,19 +97,44 @@ public: , 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) { @@ -114,6 +146,8 @@ private: void set (double seconds, int tcr); }; + } + #endif diff --git a/src/decrypted_kdm.cc b/src/decrypted_kdm.cc index 0a3eeabd..174efb1b 100644 --- a/src/decrypted_kdm.cc +++ b/src/decrypted_kdm.cc @@ -1,5 +1,5 @@ /* - Copyright (C) 2013-2017 Carl Hetherington <cth@carlh.net> + Copyright (C) 2013-2021 Carl Hetherington <cth@carlh.net> This file is part of libdcp. @@ -31,6 +31,12 @@ 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" @@ -48,6 +54,7 @@ #include <openssl/pem.h> #include <openssl/err.h> + using std::list; using std::vector; using std::string; @@ -60,9 +67,11 @@ using std::shared_ptr; 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) { @@ -70,6 +79,7 @@ put (uint8_t ** d, string s) (*d) += s.length(); } + static void put (uint8_t ** d, uint8_t const * s, int N) { @@ -77,6 +87,7 @@ put (uint8_t ** d, uint8_t const * s, int N) (*d) += N; } + void DecryptedKDM::put_uuid (uint8_t ** d, string id) { @@ -96,6 +107,7 @@ DecryptedKDM::put_uuid (uint8_t ** d, string id) *d += 16; } + string DecryptedKDM::get_uuid (unsigned char ** p) { @@ -114,6 +126,7 @@ DecryptedKDM::get_uuid (unsigned char ** p) return buffer; } + static string get (uint8_t ** p, int N) { @@ -126,16 +139,17 @@ 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); } @@ -148,7 +162,7 @@ DecryptedKDM::DecryptedKDM (EncryptedKDM const & kdm, string private_key) 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; @@ -217,6 +231,7 @@ DecryptedKDM::DecryptedKDM (EncryptedKDM const & kdm, string private_key) _issue_date = kdm.issue_date (); } + DecryptedKDM::DecryptedKDM ( LocalTime not_valid_before, LocalTime not_valid_after, @@ -233,6 +248,7 @@ DecryptedKDM::DecryptedKDM ( } + DecryptedKDM::DecryptedKDM ( string cpl_id, map<shared_ptr<const ReelMXF>, Key> keys, @@ -253,6 +269,7 @@ DecryptedKDM::DecryptedKDM ( } } + DecryptedKDM::DecryptedKDM ( shared_ptr<const CPL> cpl, Key key, @@ -282,23 +299,21 @@ DecryptedKDM::DecryptedKDM ( } } -/** @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, diff --git a/src/decrypted_kdm.h b/src/decrypted_kdm.h index 867e97ff..7bc9a217 100644 --- a/src/decrypted_kdm.h +++ b/src/decrypted_kdm.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2013-2018 Carl Hetherington <cth@carlh.net> + Copyright (C) 2013-2021 Carl Hetherington <cth@carlh.net> This file is part of libdcp. @@ -31,13 +31,16 @@ 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" @@ -46,18 +49,22 @@ #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. @@ -138,7 +145,13 @@ public: 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. */ @@ -173,6 +186,8 @@ private: std::vector<DecryptedKDMKey> _keys; }; + } + #endif diff --git a/src/decrypted_kdm_key.cc b/src/decrypted_kdm_key.cc index e5adc3c6..5d8140ae 100644 --- a/src/decrypted_kdm_key.cc +++ b/src/decrypted_kdm_key.cc @@ -1,5 +1,5 @@ /* - Copyright (C) 2013-2014 Carl Hetherington <cth@carlh.net> + Copyright (C) 2013-2021 Carl Hetherington <cth@carlh.net> This file is part of libdcp. @@ -31,10 +31,18 @@ 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) { diff --git a/src/decrypted_kdm_key.h b/src/decrypted_kdm_key.h index 3fee9a68..f1218d3f 100644 --- a/src/decrypted_kdm_key.h +++ b/src/decrypted_kdm_key.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2013-2014 Carl Hetherington <cth@carlh.net> + Copyright (C) 2013-2021 Carl Hetherington <cth@carlh.net> This file is part of libdcp. @@ -31,21 +31,26 @@ 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 { @@ -86,8 +91,11 @@ private: Standard _standard; }; + bool operator== (DecryptedKDMKey const &, DecryptedKDMKey const &); + } + #endif diff --git a/src/encrypted_kdm.cc b/src/encrypted_kdm.cc index d7326e89..dec2efcd 100644 --- a/src/encrypted_kdm.cc +++ b/src/encrypted_kdm.cc @@ -31,6 +31,12 @@ 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" @@ -44,6 +50,7 @@ #include <boost/date_time/posix_time/posix_time.hpp> #include <boost/format.hpp> + using std::list; using std::vector; using std::string; @@ -55,11 +62,14 @@ using boost::optional; 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: @@ -82,6 +92,7 @@ public: string x509_serial_number; }; + class X509Data { public: @@ -104,6 +115,7 @@ public: std::string x509_certificate; }; + class Reference { public: @@ -131,6 +143,7 @@ public: string digest_value; }; + class SignedInfo { public: @@ -171,6 +184,7 @@ private: Reference authenticated_private; }; + class Signature { public: @@ -201,6 +215,7 @@ public: vector<X509Data> x509_data; }; + class AuthenticatedPrivate { public: @@ -235,6 +250,7 @@ public: vector<string> encrypted_key; }; + class TypedKeyId { public: @@ -254,7 +270,7 @@ 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 */ @@ -269,6 +285,7 @@ public: string key_id; }; + class KeyIdList { public: @@ -291,6 +308,7 @@ public: vector<TypedKeyId> typed_key_id; }; + class AuthorizedDeviceInfo { public: @@ -323,6 +341,7 @@ public: std::vector<string> certificate_thumbprints; }; + class X509IssuerSerial { public: @@ -345,6 +364,7 @@ public: string x509_serial_number; }; + class Recipient { public: @@ -367,6 +387,7 @@ public: string x509_subject_name; }; + class KDMRequiredExtensions { public: @@ -450,9 +471,11 @@ private: 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: @@ -472,6 +495,7 @@ public: KDMRequiredExtensions kdm_required_extensions; }; + class AuthenticatedPublic { public: @@ -516,6 +540,7 @@ 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. */ @@ -559,9 +584,11 @@ public: Signature signature; }; + } } + EncryptedKDM::EncryptedKDM (string s) { try { @@ -573,7 +600,7 @@ EncryptedKDM::EncryptedKDM (string s) } } -/** @param trusted_devices Trusted device thumbprints */ + EncryptedKDM::EncryptedKDM ( shared_ptr<const CertificateChain> signer, Certificate recipient, @@ -602,7 +629,7 @@ EncryptedKDM::EncryptedKDM ( * 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; @@ -675,12 +702,14 @@ EncryptedKDM::EncryptedKDM ( _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) { @@ -693,11 +722,13 @@ EncryptedKDM::operator= (EncryptedKDM const & other) return *this; } + EncryptedKDM::~EncryptedKDM () { delete _data; } + void EncryptedKDM::as_xml (boost::filesystem::path path) const { @@ -713,66 +744,77 @@ 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 { @@ -784,6 +826,7 @@ EncryptedKDM::signer_certificate_chain () const return chain; } + bool dcp::operator== (EncryptedKDM const & a, EncryptedKDM const & b) { diff --git a/src/encrypted_kdm.h b/src/encrypted_kdm.h index 342bedca..e74dde69 100644 --- a/src/encrypted_kdm.h +++ b/src/encrypted_kdm.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2013-2016 Carl Hetherington <cth@carlh.net> + Copyright (C) 2013-2021 Carl Hetherington <cth@carlh.net> This file is part of libdcp. @@ -31,34 +31,42 @@ 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 @@ -117,11 +125,13 @@ private: std::vector<std::string> keys ); - data::EncryptedKDMData* _data; + data::EncryptedKDMData* _data = nullptr; }; + extern bool operator== (EncryptedKDM const & a, EncryptedKDM const & b); } + #endif diff --git a/src/exceptions.cc b/src/exceptions.cc index 37e699e6..30d11a68 100644 --- a/src/exceptions.cc +++ b/src/exceptions.cc @@ -1,5 +1,5 @@ /* - Copyright (C) 2014-2020 Carl Hetherington <cth@carlh.net> + Copyright (C) 2014-2021 Carl Hetherington <cth@carlh.net> This file is part of libdcp. @@ -31,18 +31,22 @@ 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) @@ -51,24 +55,28 @@ FileError::FileError (string message, boost::filesystem::path filename, int numb } + 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)) { @@ -82,24 +90,28 @@ ProgrammingError::ProgrammingError (string file, int line) } + 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) @@ -108,12 +120,14 @@ ReadError::ReadError (string message, string detail) } + 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 ? diff --git a/src/font_asset.cc b/src/font_asset.cc index f201d649..a72dc6cb 100644 --- a/src/font_asset.cc +++ b/src/font_asset.cc @@ -1,5 +1,5 @@ /* - Copyright (C) 2015 Carl Hetherington <cth@carlh.net> + Copyright (C) 2015-2021 Carl Hetherington <cth@carlh.net> This file is part of libdcp. @@ -31,22 +31,26 @@ 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) { diff --git a/src/font_asset.h b/src/font_asset.h index 1d412619..d39a6b24 100644 --- a/src/font_asset.h +++ b/src/font_asset.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2015 Carl Hetherington <cth@carlh.net> + Copyright (C) 2015-2021 Carl Hetherington <cth@carlh.net> This file is part of libdcp. @@ -31,14 +31,18 @@ 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. */ @@ -55,4 +59,5 @@ private: } }; + } diff --git a/src/frame.h b/src/frame.h index 328b22b8..74bd616f 100644 --- a/src/frame.h +++ b/src/frame.h @@ -32,6 +32,11 @@ */ +/** @file src/frame.h + * @brief Frame class + */ + + #ifndef LIBDCP_FRAME_H #define LIBDCP_FRAME_H @@ -52,7 +57,7 @@ public: 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")); @@ -1,5 +1,5 @@ /* - Copyright (C) 2020 Carl Hetherington <cth@carlh.net> + Copyright (C) 2020-2021 Carl Hetherington <cth@carlh.net> This file is part of libdcp. @@ -32,6 +32,11 @@ */ +/** @file src/fsk.cc + * @brief FSK class + */ + + #include "fsk.h" #include <iostream> @@ -42,10 +47,6 @@ using namespace dcp; FSK::FSK () - : _data_position (0) - , _sample_position (0) - , _last_polarity (false) - , _last_bit (false) { } @@ -32,6 +32,11 @@ */ +/** @file src/fsk.h + * @brief FSK class + */ + + #include <stdint.h> #include <vector> @@ -60,15 +65,16 @@ public: 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; }; + } diff --git a/src/gamma_transfer_function.cc b/src/gamma_transfer_function.cc index 34501d98..1875221e 100644 --- a/src/gamma_transfer_function.cc +++ b/src/gamma_transfer_function.cc @@ -58,7 +58,7 @@ double * 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); diff --git a/src/identity_transfer_function.cc b/src/identity_transfer_function.cc index ef18825b..c01e6698 100644 --- a/src/identity_transfer_function.cc +++ b/src/identity_transfer_function.cc @@ -1,5 +1,5 @@ /* - Copyright (C) 2016 Carl Hetherington <cth@carlh.net> + Copyright (C) 2016-2021 Carl Hetherington <cth@carlh.net> This file is part of libdcp. @@ -31,23 +31,27 @@ 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); } @@ -55,9 +59,10 @@ IdentityTransferFunction::make_lut (int bit_depth, bool) const 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); } diff --git a/src/identity_transfer_function.h b/src/identity_transfer_function.h index f2313c10..ff6814eb 100644 --- a/src/identity_transfer_function.h +++ b/src/identity_transfer_function.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2016 Carl Hetherington <cth@carlh.net> + Copyright (C) 2016-2021 Carl Hetherington <cth@carlh.net> This file is part of libdcp. @@ -31,14 +31,18 @@ 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: @@ -48,4 +52,5 @@ protected: double * make_lut (int bit_depth, bool inverse) const; }; + } diff --git a/src/interop_load_font_node.cc b/src/interop_load_font_node.cc index a5bc1428..40f12dde 100644 --- a/src/interop_load_font_node.cc +++ b/src/interop_load_font_node.cc @@ -1,5 +1,5 @@ /* - Copyright (C) 2012-2015 Carl Hetherington <cth@carlh.net> + Copyright (C) 2012-2021 Carl Hetherington <cth@carlh.net> This file is part of libdcp. @@ -31,14 +31,22 @@ 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_) @@ -46,23 +54,26 @@ InteropLoadFontNode::InteropLoadFontNode (string id_, string 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) { diff --git a/src/interop_load_font_node.h b/src/interop_load_font_node.h index 17ce1893..6fe3fb1c 100644 --- a/src/interop_load_font_node.h +++ b/src/interop_load_font_node.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net> + Copyright (C) 2012-2021 Carl Hetherington <cth@carlh.net> This file is part of libdcp. @@ -31,13 +31,21 @@ 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: @@ -48,7 +56,9 @@ public: std::string uri; }; + bool operator== (InteropLoadFontNode const & a, InteropLoadFontNode const & b); bool operator!= (InteropLoadFontNode const & a, InteropLoadFontNode const & b); + } diff --git a/src/interop_subtitle_asset.cc b/src/interop_subtitle_asset.cc index 9c977b44..938c028e 100644 --- a/src/interop_subtitle_asset.cc +++ b/src/interop_subtitle_asset.cc @@ -31,6 +31,12 @@ 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" @@ -46,6 +52,7 @@ #include <cmath> #include <cstdio> + using std::list; using std::string; using std::cout; @@ -59,12 +66,13 @@ using boost::shared_array; 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"); @@ -75,9 +83,8 @@ InteropSubtitleAsset::InteropSubtitleAsset (boost::filesystem::path file) /* 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); } @@ -91,16 +98,18 @@ InteropSubtitleAsset::InteropSubtitleAsset (boost::filesystem::path file) } } + 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); @@ -119,14 +128,16 @@ InteropSubtitleAsset::xml_as_string () const 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 { @@ -134,7 +145,7 @@ InteropSubtitleAsset::equals (shared_ptr<const Asset> other_asset, EqualityOptio 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; } @@ -167,6 +178,7 @@ InteropSubtitleAsset::equals (shared_ptr<const Asset> other_asset, EqualityOptio return true; } + vector<shared_ptr<LoadFontNode>> InteropSubtitleAsset::load_font_nodes () const { @@ -175,16 +187,16 @@ 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); @@ -213,6 +225,7 @@ InteropSubtitleAsset::write (boost::filesystem::path p) const } } + /** 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. @@ -242,6 +255,7 @@ InteropSubtitleAsset::resolve_fonts (vector<shared_ptr<Asset>> assets) } } + void InteropSubtitleAsset::add_font_assets (vector<shared_ptr<Asset>>& assets) { @@ -251,6 +265,7 @@ InteropSubtitleAsset::add_font_assets (vector<shared_ptr<Asset>>& assets) } } + void InteropSubtitleAsset::write_to_assetmap (xmlpp::Node* node, boost::filesystem::path root) const { @@ -265,6 +280,7 @@ InteropSubtitleAsset::write_to_assetmap (xmlpp::Node* node, boost::filesystem::p } } + void InteropSubtitleAsset::add_to_pkl (shared_ptr<PKL> pkl, boost::filesystem::path root) const { diff --git a/src/interop_subtitle_asset.h b/src/interop_subtitle_asset.h index 41e04f97..07bfeadf 100644 --- a/src/interop_subtitle_asset.h +++ b/src/interop_subtitle_asset.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2012-2015 Carl Hetherington <cth@carlh.net> + Copyright (C) 2012-2021 Carl Hetherington <cth@carlh.net> This file is part of libdcp. @@ -31,19 +31,24 @@ 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. */ @@ -67,7 +72,10 @@ public: 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); @@ -1,5 +1,5 @@ /* - Copyright (C) 2012-2015 Carl Hetherington <cth@carlh.net> + Copyright (C) 2012-2021 Carl Hetherington <cth@carlh.net> This file is part of libdcp. @@ -32,6 +32,11 @@ */ +/** @file src/j2k.cc + * @brief Methods to encode and decode JPEG2000 + */ + + #include "array_data.h" #include "j2k.h" #include "exceptions.h" @@ -42,6 +47,7 @@ #include <cmath> #include <iostream> + using std::min; using std::pow; using std::string; @@ -49,12 +55,14 @@ using std::shared_ptr; 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 @@ -80,12 +88,14 @@ private: 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) { @@ -106,15 +116,7 @@ compress_error_callback (char const * msg, void *) 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) { @@ -131,12 +133,12 @@ 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")); } @@ -145,7 +147,7 @@ dcp::decompress_j2k (uint8_t* data, int64_t size, int reduce) 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"); } @@ -153,7 +155,7 @@ dcp::decompress_j2k (uint8_t* data, int64_t size, int reduce) 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); @@ -176,28 +178,22 @@ dcp::decompress_j2k (uint8_t* data, int64_t size, int reduce) 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); @@ -213,14 +209,16 @@ dcp::decompress_j2k (uint8_t* data, int64_t size, int reduce) } #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); @@ -231,7 +229,7 @@ public: 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; @@ -253,33 +251,35 @@ private: 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"); } @@ -312,7 +312,7 @@ dcp::compress_j2k (shared_ptr<const OpenJPEGImage> xyz, int bandwidth, int frame /* 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); @@ -358,9 +358,12 @@ dcp::compress_j2k (shared_ptr<const OpenJPEGImage> xyz, int bandwidth, int frame 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) { @@ -373,8 +376,8 @@ dcp::compress_j2k (shared_ptr<const OpenJPEGImage> xyz, int bandwidth, int frame 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"); } @@ -453,10 +456,10 @@ dcp::compress_j2k (shared_ptr<const OpenJPEGImage> xyz, int bandwidth, int frame 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"); } @@ -1,5 +1,5 @@ /* - Copyright (C) 2012-2016 Carl Hetherington <cth@carlh.net> + Copyright (C) 2012-2021 Carl Hetherington <cth@carlh.net> This file is part of libdcp. @@ -32,16 +32,39 @@ */ +/** @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"); + } diff --git a/src/language_tag.cc b/src/language_tag.cc index 07e95564..c2e81869 100644 --- a/src/language_tag.cc +++ b/src/language_tag.cc @@ -32,6 +32,11 @@ */ +/** @file src/language_tag.cc + * @brief LanguageTag class + */ + + #include "compose.hpp" #include "dcp_assert.h" #include "exceptions.h" @@ -67,7 +72,7 @@ find_in_list (vector<LanguageTag::SubtagData> const& list, string subtag) } } - return optional<LanguageTag::SubtagData>(); + return {}; } @@ -147,7 +152,7 @@ LanguageTag::to_string () const throw LanguageTagError("No language set up"); } - string s = _language->subtag(); + auto s = _language->subtag(); if (_script) { s += "-" + _script->subtag(); @@ -264,19 +269,19 @@ LanguageTag::description () const 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; } @@ -321,7 +326,7 @@ LanguageTag::subtag_type_name (SubtagType type) return "Extended"; } - return ""; + return {}; } bool @@ -412,16 +417,16 @@ LanguageTag::get_subtag_data (LanguageTag::SubtagType type, string subtag) 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; @@ -431,7 +436,7 @@ LanguageTag::get_subtag_description (LanguageTag::SubtagType type, string subtag 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); } diff --git a/src/language_tag.h b/src/language_tag.h index 06134b03..3b0b6ac9 100644 --- a/src/language_tag.h +++ b/src/language_tag.h @@ -31,6 +31,12 @@ 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 @@ -232,12 +238,14 @@ private: 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 diff --git a/src/load_font_node.h b/src/load_font_node.h index 068f7d21..b57eb3c4 100644 --- a/src/load_font_node.h +++ b/src/load_font_node.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2012-2015 Carl Hetherington <cth@carlh.net> + Copyright (C) 2012-2021 Carl Hetherington <cth@carlh.net> This file is part of libdcp. @@ -31,16 +31,20 @@ 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 { diff --git a/src/local_time.cc b/src/local_time.cc index 6a8579ff..892ffba4 100644 --- a/src/local_time.cc +++ b/src/local_time.cc @@ -1,5 +1,5 @@ /* - Copyright (C) 2014-2020 Carl Hetherington <cth@carlh.net> + Copyright (C) 2014-2021 Carl Hetherington <cth@carlh.net> This file is part of libdcp. @@ -31,10 +31,12 @@ 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" @@ -44,26 +46,29 @@ #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) { @@ -76,15 +81,14 @@ 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) { @@ -98,10 +102,7 @@ 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); @@ -109,19 +110,20 @@ LocalTime::LocalTime (boost::posix_time::ptime t, int tz_hour, int tz_minute) _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 */ @@ -163,15 +165,15 @@ LocalTime::LocalTime (string s) 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; @@ -179,7 +181,7 @@ LocalTime::LocalTime (string s) } } -/** @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 { @@ -192,7 +194,7 @@ LocalTime::as_string (bool with_millisecond) const return buffer; } -/** @return The date in the form YYYY-MM-DD */ + string LocalTime::date () const { @@ -201,7 +203,7 @@ 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 { @@ -249,6 +251,7 @@ LocalTime::add_months (int m) set (posix_time::ptime(d, posix_time::time_duration(_hour, _minute, _second, _millisecond * 1000))); } + void LocalTime::add_minutes (int m) { @@ -259,6 +262,7 @@ LocalTime::add_minutes (int m) set (t); } + bool LocalTime::operator== (LocalTime const & other) const { @@ -267,6 +271,7 @@ LocalTime::operator== (LocalTime const & other) const _tz_hour == other._tz_hour && _tz_minute == other._tz_minute; } + bool LocalTime::operator< (LocalTime const & other) const { @@ -288,12 +293,14 @@ 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) { diff --git a/src/local_time.h b/src/local_time.h index e818ba6e..a5a479cd 100644 --- a/src/local_time.h +++ b/src/local_time.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2014-2020 Carl Hetherington <cth@carlh.net> + Copyright (C) 2014-2021 Carl Hetherington <cth@carlh.net> This file is part of libdcp. @@ -31,20 +31,26 @@ 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). @@ -57,14 +63,32 @@ namespace dcp { 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 { @@ -99,24 +123,27 @@ private: 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 diff --git a/src/locale_convert.cc b/src/locale_convert.cc index 915cac82..2c7c74ef 100644 --- a/src/locale_convert.cc +++ b/src/locale_convert.cc @@ -1,5 +1,5 @@ /* - Copyright (C) 2016 Carl Hetherington <cth@carlh.net> + Copyright (C) 2016-2021 Carl Hetherington <cth@carlh.net> This file is part of libdcp. @@ -31,13 +31,21 @@ 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) @@ -47,6 +55,7 @@ dcp::locale_convert (unsigned char x, int, bool) return buffer; } + template<> string dcp::locale_convert (unsigned short int x, int, bool) @@ -56,6 +65,7 @@ dcp::locale_convert (unsigned short int x, int, bool) return buffer; } + template<> string dcp::locale_convert (int x, int, bool) @@ -65,6 +75,7 @@ dcp::locale_convert (int x, int, bool) return buffer; } + template<> string dcp::locale_convert (unsigned int x, int, bool) @@ -74,6 +85,7 @@ dcp::locale_convert (unsigned int x, int, bool) return buffer; } + template<> string dcp::locale_convert (long int x, int, bool) @@ -87,6 +99,7 @@ dcp::locale_convert (long int x, int, bool) return buffer; } + template<> string dcp::locale_convert (unsigned long int x, int, bool) @@ -96,6 +109,7 @@ dcp::locale_convert (unsigned long int x, int, bool) return buffer; } + template<> string dcp::locale_convert (long long int x, int, bool) @@ -109,6 +123,7 @@ dcp::locale_convert (long long int x, int, bool) return buffer; } + template<> string dcp::locale_convert (unsigned long long int x, int, bool) @@ -122,6 +137,7 @@ dcp::locale_convert (unsigned long long int x, int, bool) return buffer; } + template<> string dcp::locale_convert (float x, int precision, bool fixed) @@ -137,6 +153,7 @@ dcp::locale_convert (float x, int precision, bool fixed) return buffer; } + template<> string dcp::locale_convert (double x, int precision, bool fixed) @@ -152,6 +169,7 @@ dcp::locale_convert (double x, int precision, bool fixed) return buffer; } + template<> string dcp::locale_convert (string x, int, bool) @@ -159,6 +177,7 @@ dcp::locale_convert (string x, int, bool) return x; } + template<> string dcp::locale_convert (char* x, int, bool) @@ -166,6 +185,7 @@ dcp::locale_convert (char* x, int, bool) return x; } + template<> string dcp::locale_convert (char const * x, int, bool) @@ -173,6 +193,7 @@ dcp::locale_convert (char const * x, int, bool) return x; } + template<> string dcp::locale_convert (wchar_t const * x, int, bool) @@ -181,6 +202,7 @@ dcp::locale_convert (wchar_t const * x, int, bool) return string (s.begin(), s.end()); } + template<> string dcp::locale_convert (char x, int, bool) @@ -190,6 +212,7 @@ dcp::locale_convert (char x, int, bool) return s; } + template<> string dcp::locale_convert (boost::filesystem::path x, int, bool) @@ -197,6 +220,7 @@ dcp::locale_convert (boost::filesystem::path x, int, bool) return x.string(); } + template<> unsigned char dcp::locale_convert (string x, int, bool) @@ -206,6 +230,7 @@ dcp::locale_convert (string x, int, bool) return y; } + template<> unsigned short int dcp::locale_convert (string x, int, bool) @@ -215,6 +240,7 @@ dcp::locale_convert (string x, int, bool) return y; } + template<> unsigned int dcp::locale_convert (string x, int, bool) @@ -224,6 +250,7 @@ dcp::locale_convert (string x, int, bool) return y; } + template<> int dcp::locale_convert (string x, int, bool) @@ -233,6 +260,7 @@ dcp::locale_convert (string x, int, bool) return y; } + template<> long dcp::locale_convert (string x, int, bool) @@ -242,6 +270,7 @@ dcp::locale_convert (string x, int, bool) return y; } + template<> unsigned long dcp::locale_convert (string x, int, bool) @@ -255,6 +284,7 @@ dcp::locale_convert (string x, int, bool) return y; } + template<> long long dcp::locale_convert (string x, int, bool) @@ -268,6 +298,7 @@ dcp::locale_convert (string x, int, bool) return y; } + template<> unsigned long long dcp::locale_convert (string x, int, bool) @@ -281,6 +312,7 @@ dcp::locale_convert (string x, int, bool) return y; } + template<> float dcp::locale_convert (string x, int, bool) @@ -290,6 +322,7 @@ dcp::locale_convert (string x, int, bool) return y; } + template<> double dcp::locale_convert (string x, int, bool) diff --git a/src/locale_convert.h b/src/locale_convert.h index ab1984e4..9b1b432c 100644 --- a/src/locale_convert.h +++ b/src/locale_convert.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2016 Carl Hetherington <cth@carlh.net> + Copyright (C) 2016-2021 Carl Hetherington <cth@carlh.net> This file is part of libdcp. @@ -31,17 +31,26 @@ 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) @@ -158,6 +167,8 @@ template <> double locale_convert (std::string x, int, bool); + } + #endif diff --git a/src/metadata.cc b/src/metadata.cc index 6fedc61e..750143d1 100644 --- a/src/metadata.cc +++ b/src/metadata.cc @@ -1,5 +1,5 @@ /* - Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net> + Copyright (C) 2012-2021 Carl Hetherington <cth@carlh.net> This file is part of libdcp. @@ -31,10 +31,12 @@ 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" @@ -42,9 +44,10 @@ #include <iomanip> #include <time.h> -using namespace std; + using namespace dcp; + MXFMetadata::MXFMetadata () : company_name ("libdcp") , product_name ("libdcp") @@ -53,6 +56,7 @@ MXFMetadata::MXFMetadata () } + void MXFMetadata::read (ASDCP::WriterInfo const & info) { diff --git a/src/metadata.h b/src/metadata.h index b24265f3..364cb388 100644 --- a/src/metadata.h +++ b/src/metadata.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net> + Copyright (C) 2012-2021 Carl Hetherington <cth@carlh.net> This file is part of libdcp. @@ -31,24 +31,31 @@ 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 */ @@ -69,6 +76,8 @@ public: std::string product_version; }; + } + #endif diff --git a/src/modified_gamma_transfer_function.cc b/src/modified_gamma_transfer_function.cc index bb388689..039e9284 100644 --- a/src/modified_gamma_transfer_function.cc +++ b/src/modified_gamma_transfer_function.cc @@ -1,5 +1,5 @@ /* - Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net> + Copyright (C) 2012-2021 Carl Hetherington <cth@carlh.net> This file is part of libdcp. @@ -31,14 +31,22 @@ 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) @@ -48,6 +56,7 @@ ModifiedGammaTransferFunction::ModifiedGammaTransferFunction (double power, doub } + double * ModifiedGammaTransferFunction::make_lut (int bit_depth, bool inverse) const { @@ -56,7 +65,7 @@ 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 { @@ -65,7 +74,7 @@ ModifiedGammaTransferFunction::make_lut (int bit_depth, bool inverse) const } } 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 { @@ -77,18 +86,19 @@ ModifiedGammaTransferFunction::make_lut (int bit_depth, bool inverse) const 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 ); } diff --git a/src/modified_gamma_transfer_function.h b/src/modified_gamma_transfer_function.h index b38a16b0..70018cbf 100644 --- a/src/modified_gamma_transfer_function.h +++ b/src/modified_gamma_transfer_function.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net> + Copyright (C) 2012-2021 Carl Hetherington <cth@carlh.net> This file is part of libdcp. @@ -31,14 +31,18 @@ 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 @@ -82,4 +86,5 @@ private: double _B; }; + } diff --git a/src/mono_picture_asset.cc b/src/mono_picture_asset.cc index 89661061..78ab8709 100644 --- a/src/mono_picture_asset.cc +++ b/src/mono_picture_asset.cc @@ -31,6 +31,12 @@ 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" @@ -41,6 +47,7 @@ #include <asdcp/AS_DCP.h> #include <asdcp/KM_fileio.h> + using std::string; using std::vector; using std::list; @@ -53,6 +60,7 @@ using namespace boost::placeholders; #endif using namespace dcp; + MonoPictureAsset::MonoPictureAsset (boost::filesystem::path file) : PictureAsset (file) { @@ -77,18 +85,21 @@ MonoPictureAsset::MonoPictureAsset (boost::filesystem::path 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 { @@ -170,16 +181,20 @@ MonoPictureAsset::equals (shared_ptr<const Asset> other, EqualityOptions opt, No 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 diff --git a/src/mono_picture_asset.h b/src/mono_picture_asset.h index 28913f61..8c152146 100644 --- a/src/mono_picture_asset.h +++ b/src/mono_picture_asset.h @@ -31,18 +31,28 @@ 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 { diff --git a/src/mono_picture_asset_reader.h b/src/mono_picture_asset_reader.h index 4caf80f9..5bead791 100644 --- a/src/mono_picture_asset_reader.h +++ b/src/mono_picture_asset_reader.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2016 Carl Hetherington <cth@carlh.net> + Copyright (C) 2016-2021 Carl Hetherington <cth@carlh.net> This file is part of libdcp. @@ -31,16 +31,27 @@ 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 diff --git a/src/mono_picture_asset_writer.cc b/src/mono_picture_asset_writer.cc index 01fb11f0..dec120cb 100644 --- a/src/mono_picture_asset_writer.cc +++ b/src/mono_picture_asset_writer.cc @@ -1,5 +1,5 @@ /* - Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net> + Copyright (C) 2012-2021 Carl Hetherington <cth@carlh.net> This file is part of libdcp. @@ -31,10 +31,12 @@ 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" @@ -43,17 +45,21 @@ #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. */ @@ -64,6 +70,7 @@ MonoPictureAssetWriter::MonoPictureAssetWriter (PictureAsset* asset, boost::file } + void MonoPictureAssetWriter::start (uint8_t const * data, int size) { @@ -71,6 +78,7 @@ 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) { @@ -80,15 +88,15 @@ 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)); } @@ -96,27 +104,29 @@ MonoPictureAssetWriter::write (uint8_t const * data, int size) 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)); } } diff --git a/src/mono_picture_asset_writer.h b/src/mono_picture_asset_writer.h index a5799d27..9dffaa24 100644 --- a/src/mono_picture_asset_writer.h +++ b/src/mono_picture_asset_writer.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2012-2015 Carl Hetherington <cth@carlh.net> + Copyright (C) 2012-2021 Carl Hetherington <cth@carlh.net> This file is part of libdcp. @@ -31,21 +31,26 @@ 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 * @@ -59,8 +64,6 @@ namespace dcp { 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 (); @@ -68,6 +71,8 @@ public: 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 @@ -77,6 +82,8 @@ private: std::shared_ptr<ASDCPState> _state; }; + } + #endif diff --git a/src/mono_picture_frame.cc b/src/mono_picture_frame.cc index 7420193e..3e27bed7 100644 --- a/src/mono_picture_frame.cc +++ b/src/mono_picture_frame.cc @@ -1,5 +1,5 @@ /* - Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net> + Copyright (C) 2012-2021 Carl Hetherington <cth@carlh.net> This file is part of libdcp. @@ -31,10 +31,12 @@ 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" @@ -46,33 +48,34 @@ #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. @@ -81,50 +84,47 @@ MonoPictureFrame::MonoPictureFrame (boost::filesystem::path path) 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); } diff --git a/src/mono_picture_frame.h b/src/mono_picture_frame.h index d6774aef..52cf7965 100644 --- a/src/mono_picture_frame.h +++ b/src/mono_picture_frame.h @@ -32,22 +32,22 @@ */ -#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 { @@ -66,21 +66,33 @@ class OpenJPEGImage; /** @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: @@ -1,5 +1,5 @@ /* - Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net> + Copyright (C) 2012-2021 Carl Hetherington <cth@carlh.net> This file is part of libdcp. @@ -31,10 +31,12 @@ 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" @@ -49,6 +51,7 @@ #include <boost/filesystem.hpp> #include <iostream> + using std::string; using std::cout; using std::list; @@ -57,6 +60,7 @@ using std::shared_ptr; using std::dynamic_pointer_cast; using namespace dcp; + MXF::MXF () : _context_id (make_uuid ()) { @@ -65,6 +69,7 @@ MXF::MXF () */ } + MXF::MXF (Standard standard) : _context_id (make_uuid ()) , _standard (standard) @@ -72,6 +77,7 @@ MXF::MXF (Standard standard) } + void MXF::fill_writer_info (ASDCP::WriterInfo* writer_info, string id) const { @@ -101,11 +107,7 @@ 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) { @@ -117,6 +119,7 @@ MXF::set_key (Key key) } } + string MXF::read_writer_info (ASDCP::WriterInfo const & info) { @@ -1,5 +1,5 @@ /* - Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net> + Copyright (C) 2012-2021 Carl Hetherington <cth@carlh.net> This file is part of libdcp. @@ -31,33 +31,44 @@ 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 { @@ -82,6 +93,11 @@ public: 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 */ @@ -139,6 +155,8 @@ protected: boost::optional<Standard> _standard; }; + } + #endif diff --git a/src/name_format.cc b/src/name_format.cc index 11b68e19..e5c6556e 100644 --- a/src/name_format.cc +++ b/src/name_format.cc @@ -1,5 +1,5 @@ /* - Copyright (C) 2016 Carl Hetherington <cth@carlh.net> + Copyright (C) 2016-2021 Carl Hetherington <cth@carlh.net> This file is part of libdcp. @@ -31,14 +31,22 @@ 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) { @@ -51,6 +59,7 @@ filter (char c) return c; } + static string filter (string c) { @@ -64,13 +73,6 @@ 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 { @@ -79,7 +81,7 @@ 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; @@ -95,6 +97,7 @@ NameFormat::get (Map values, string suffix, string ignore) const return result + suffix; } + bool dcp::operator== (NameFormat const & a, NameFormat const & b) { diff --git a/src/name_format.h b/src/name_format.h index e6fc9d72..6401fe82 100644 --- a/src/name_format.h +++ b/src/name_format.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2016 Carl Hetherington <cth@carlh.net> + Copyright (C) 2016-2021 Carl Hetherington <cth@carlh.net> This file is part of libdcp. @@ -31,16 +31,25 @@ 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: @@ -60,14 +69,24 @@ 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 diff --git a/src/openjpeg_image.cc b/src/openjpeg_image.cc index 31889566..3594b2bd 100644 --- a/src/openjpeg_image.cc +++ b/src/openjpeg_image.cc @@ -1,5 +1,5 @@ /* - Copyright (C) 2012-2015 Carl Hetherington <cth@carlh.net> + Copyright (C) 2012-2021 Carl Hetherington <cth@carlh.net> This file is part of libdcp. @@ -31,36 +31,42 @@ 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)); @@ -80,17 +86,13 @@ OpenJPEGImage::OpenJPEGImage (OpenJPEGImage const & other) 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); @@ -108,6 +110,7 @@ OpenJPEGImage::OpenJPEGImage (uint8_t const * data_16, dcp::Size size, int strid } } + void OpenJPEGImage::create (Size size) { @@ -137,15 +140,13 @@ 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 { @@ -153,7 +154,7 @@ OpenJPEGImage::data (int c) const return _opj_image->comps[c].data; } -/** @return Size of the image in pixels */ + dcp::Size OpenJPEGImage::size () const { @@ -161,18 +162,21 @@ 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 { diff --git a/src/openjpeg_image.h b/src/openjpeg_image.h index 002e2a83..2138a21e 100644 --- a/src/openjpeg_image.h +++ b/src/openjpeg_image.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2012-2015 Carl Hetherington <cth@carlh.net> + Copyright (C) 2012-2021 Carl Hetherington <cth@carlh.net> This file is part of libdcp. @@ -31,31 +31,53 @@ 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; @@ -70,7 +92,8 @@ public: 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 }; + } diff --git a/src/picture_asset.cc b/src/picture_asset.cc index 6b5e9393..86d85d46 100644 --- a/src/picture_asset.cc +++ b/src/picture_asset.cc @@ -1,5 +1,5 @@ /* - Copyright (C) 2012-2015 Carl Hetherington <cth@carlh.net> + Copyright (C) 2012-2021 Carl Hetherington <cth@carlh.net> This file is part of libdcp. @@ -31,6 +31,12 @@ 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" @@ -46,6 +52,7 @@ #include <list> #include <stdexcept> + using std::string; using std::list; using std::vector; @@ -55,7 +62,7 @@ using std::make_pair; using std::shared_ptr; using namespace dcp; -/** Load a PictureAsset from a file */ + PictureAsset::PictureAsset (boost::filesystem::path file) : Asset (file) , _intrinsic_duration (0) @@ -63,7 +70,7 @@ PictureAsset::PictureAsset (boost::filesystem::path file) } -/** Create a new PictureAsset with a given edit rate and standard */ + PictureAsset::PictureAsset (Fraction edit_rate, Standard standard) : MXF (standard) , _edit_rate (edit_rate) @@ -72,6 +79,7 @@ PictureAsset::PictureAsset (Fraction edit_rate, Standard standard) } + void PictureAsset::read_picture_descriptor (ASDCP::JP2K::PictureDescriptor const & desc) { @@ -83,6 +91,7 @@ PictureAsset::read_picture_descriptor (ASDCP::JP2K::PictureDescriptor const & de _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 @@ -125,6 +134,7 @@ PictureAsset::descriptor_equals ( return true; } + bool PictureAsset::frame_buffer_equals ( int frame, EqualityOptions opt, NoteHandler note, @@ -138,8 +148,8 @@ PictureAsset::frame_buffer_equals ( } /* 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 */ @@ -170,11 +180,11 @@ PictureAsset::frame_buffer_equals ( 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)); @@ -199,6 +209,7 @@ PictureAsset::frame_buffer_equals ( return true; } + string PictureAsset::static_pkl_type (Standard standard) { @@ -212,6 +223,7 @@ PictureAsset::static_pkl_type (Standard standard) } } + string PictureAsset::pkl_type (Standard standard) const { diff --git a/src/picture_asset.h b/src/picture_asset.h index a49d1a7d..6ee3bd24 100644 --- a/src/picture_asset.h +++ b/src/picture_asset.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net> + Copyright (C) 2012-2021 Carl Hetherington <cth@carlh.net> This file is part of libdcp. @@ -31,37 +31,46 @@ 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 ( @@ -124,7 +133,7 @@ protected: /** 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; @@ -137,4 +146,5 @@ private: } + #endif diff --git a/src/picture_asset_writer.cc b/src/picture_asset_writer.cc index a8dee68c..f9f6630c 100644 --- a/src/picture_asset_writer.cc +++ b/src/picture_asset_writer.cc @@ -1,5 +1,5 @@ /* - Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net> + Copyright (C) 2012-2021 Carl Hetherington <cth@carlh.net> This file is part of libdcp. @@ -31,6 +31,12 @@ 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" @@ -39,10 +45,12 @@ #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) diff --git a/src/picture_asset_writer.h b/src/picture_asset_writer.h index 12530513..2fcd2de1 100644 --- a/src/picture_asset_writer.h +++ b/src/picture_asset_writer.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net> + Copyright (C) 2012-2021 Carl Hetherington <cth@carlh.net> This file is part of libdcp. @@ -31,13 +31,16 @@ 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" @@ -46,19 +49,19 @@ #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) @@ -66,11 +69,12 @@ struct FrameInfo , 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. */ @@ -87,9 +91,11 @@ protected: PictureAssetWriter (PictureAsset *, boost::filesystem::path, bool); PictureAsset* _picture_asset; - bool _overwrite; + bool _overwrite = false; }; + } + #endif diff --git a/src/picture_asset_writer_common.cc b/src/picture_asset_writer_common.cc index 6591823f..e719be72 100644 --- a/src/picture_asset_writer_common.cc +++ b/src/picture_asset_writer_common.cc @@ -1,5 +1,5 @@ /* - Copyright (C) 2012-2015 Carl Hetherington <cth@carlh.net> + Copyright (C) 2012-2021 Carl Hetherington <cth@carlh.net> This file is part of libdcp. @@ -31,10 +31,18 @@ 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 () @@ -47,14 +55,16 @@ struct 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")); } @@ -66,7 +76,7 @@ void dcp::start (PictureAssetWriter* writer, shared_ptr<P> state, Q* asset, uint 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, @@ -74,8 +84,8 @@ void dcp::start (PictureAssetWriter* writer, shared_ptr<P> state, Q* asset, uint 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; @@ -32,6 +32,11 @@ */ +/** @file src/pkl.cc + * @brief PKL class + */ + + #include "pkl.h" #include "exceptions.h" #include "util.h" @@ -32,6 +32,11 @@ */ +/** @file src/pkl.cc + * @brief PKL class + */ + + #ifndef LIBDCP_PKL_H #define LIBDCP_PKL_H @@ -137,6 +142,8 @@ private: mutable boost::optional<boost::filesystem::path> _file; }; + } + #endif diff --git a/src/raw_convert.cc b/src/raw_convert.cc index b4dcb5be..7d3d1a72 100644 --- a/src/raw_convert.cc +++ b/src/raw_convert.cc @@ -1,5 +1,5 @@ /* - Copyright (C) 2014-2016 Carl Hetherington <cth@carlh.net> + Copyright (C) 2014-2021 Carl Hetherington <cth@carlh.net> This file is part of libdcp. @@ -31,13 +31,16 @@ 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 @@ -50,6 +53,7 @@ make_raw (string v) return v; } + static string make_local (string v) @@ -60,6 +64,7 @@ make_local (string v) return v; } + template <> string dcp::raw_convert (unsigned char v, int precision, bool fixed) @@ -67,6 +72,7 @@ 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) @@ -74,6 +80,7 @@ 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) @@ -81,6 +88,7 @@ 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) @@ -88,6 +96,7 @@ 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) @@ -95,6 +104,7 @@ 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) @@ -102,6 +112,7 @@ 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) @@ -109,6 +120,7 @@ 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) @@ -116,6 +128,7 @@ 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) @@ -123,6 +136,7 @@ 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) @@ -130,6 +144,7 @@ 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) @@ -137,6 +152,7 @@ dcp::raw_convert (char const * v, int, bool) return v; } + template <> string dcp::raw_convert (char* v, int, bool) @@ -144,6 +160,7 @@ dcp::raw_convert (char* v, int, bool) return v; } + template <> string dcp::raw_convert (string v, int, bool) @@ -151,6 +168,7 @@ dcp::raw_convert (string v, int, bool) return v; } + template <> string dcp::raw_convert (char v, int, bool) @@ -160,6 +178,7 @@ dcp::raw_convert (char v, int, bool) return s; } + template <> string dcp::raw_convert (wchar_t const * v, int, bool) @@ -168,6 +187,7 @@ 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) @@ -175,6 +195,7 @@ 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) @@ -182,6 +203,7 @@ 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) @@ -189,6 +211,7 @@ 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) @@ -196,6 +219,7 @@ 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) @@ -203,6 +227,7 @@ 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) @@ -210,6 +235,7 @@ 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) @@ -217,6 +243,7 @@ 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) @@ -224,6 +251,7 @@ 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) @@ -231,6 +259,7 @@ 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) @@ -238,6 +267,7 @@ 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) @@ -245,6 +275,7 @@ 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) diff --git a/src/raw_convert.h b/src/raw_convert.h index 2a0d7add..dff860e9 100644 --- a/src/raw_convert.h +++ b/src/raw_convert.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2014 Carl Hetherington <cth@carlh.net> + Copyright (C) 2014-2021 Carl Hetherington <cth@carlh.net> This file is part of libdcp. @@ -31,15 +31,24 @@ 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). */ @@ -163,6 +172,8 @@ template <> double raw_convert (char const * v, int, bool); + } + #endif diff --git a/src/reel.cc b/src/reel.cc index 16316487..74107ed0 100644 --- a/src/reel.cc +++ b/src/reel.cc @@ -32,6 +32,11 @@ */ +/** @file src/reel.cc + * @brief Reel class + */ + + #include "reel.h" #include "util.h" #include "picture_asset.h" @@ -32,6 +32,11 @@ */ +/** @file src/reel.cc + * @brief Reel class + */ + + #ifndef LIBDCP_REEL_H #define LIBDCP_REEL_H diff --git a/src/reel_asset.cc b/src/reel_asset.cc index 4d26e4f4..0f47e08d 100644 --- a/src/reel_asset.cc +++ b/src/reel_asset.cc @@ -1,5 +1,5 @@ /* - Copyright (C) 2014-2015 Carl Hetherington <cth@carlh.net> + Copyright (C) 2014-2021 Carl Hetherington <cth@carlh.net> This file is part of libdcp. @@ -31,10 +31,12 @@ 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" @@ -43,6 +45,7 @@ #include <libcxml/cxml.h> #include <libxml++/libxml++.h> + using std::pair; using std::string; using std::make_pair; @@ -50,12 +53,7 @@ using std::shared_ptr; 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) @@ -66,6 +64,7 @@ ReelAsset::ReelAsset (string id, Fraction edit_rate, int64_t 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")) @@ -77,15 +76,16 @@ ReelAsset::ReelAsset (shared_ptr<const cxml::Node> node) } + 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); } @@ -105,18 +105,21 @@ ReelAsset::write_to_cpl_asset (xmlpp::Node* node, Standard standard, optional<st 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 { @@ -153,7 +156,7 @@ ReelAsset::asset_equals (shared_ptr<const ReelAsset> other, EqualityOptions opt, return true; } -/** @return <Duration>, or <IntrinsicDuration> - <EntryPoint> if <Duration> is not present */ + int64_t ReelAsset::actual_duration () const { diff --git a/src/reel_asset.h b/src/reel_asset.h index daf2220a..344e41c3 100644 --- a/src/reel_asset.h +++ b/src/reel_asset.h @@ -31,30 +31,38 @@ 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. * @@ -65,7 +73,14 @@ class Asset; 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; @@ -98,6 +113,7 @@ public: return _duration; } + /** @return <Duration>, or <IntrinsicDuration> - <EntryPoint> if <Duration> is not present */ int64_t actual_duration () const; std::string annotation_text () const { @@ -125,7 +141,7 @@ protected: 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: diff --git a/src/reel_atmos_asset.cc b/src/reel_atmos_asset.cc index 9dccbbcb..d9e290a9 100644 --- a/src/reel_atmos_asset.cc +++ b/src/reel_atmos_asset.cc @@ -1,5 +1,5 @@ /* - Copyright (C) 2016-2017 Carl Hetherington <cth@carlh.net> + Copyright (C) 2016-2021 Carl Hetherington <cth@carlh.net> This file is part of libdcp. @@ -31,21 +31,25 @@ 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()) @@ -53,6 +57,7 @@ ReelAtmosAsset::ReelAtmosAsset (std::shared_ptr<AtmosAsset> asset, int64_t entry } + ReelAtmosAsset::ReelAtmosAsset (std::shared_ptr<const cxml::Node> node) : ReelAsset (node) , ReelMXF (node) @@ -61,39 +66,45 @@ ReelAtmosAsset::ReelAtmosAsset (std::shared_ptr<const cxml::Node> 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; } diff --git a/src/reel_atmos_asset.h b/src/reel_atmos_asset.h index 92077fc0..51e93248 100644 --- a/src/reel_atmos_asset.h +++ b/src/reel_atmos_asset.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2016-2017 Carl Hetherington <cth@carlh.net> + Copyright (C) 2016-2021 Carl Hetherington <cth@carlh.net> This file is part of libdcp. @@ -31,23 +31,29 @@ 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 { @@ -68,6 +74,8 @@ private: std::pair<std::string, std::string> cpl_node_namespace (Standard) const; }; + } + #endif diff --git a/src/reel_closed_caption_asset.cc b/src/reel_closed_caption_asset.cc index 2aa13ead..3369fdd9 100644 --- a/src/reel_closed_caption_asset.cc +++ b/src/reel_closed_caption_asset.cc @@ -1,5 +1,5 @@ /* - Copyright (C) 2012-2017 Carl Hetherington <cth@carlh.net> + Copyright (C) 2012-2021 Carl Hetherington <cth@carlh.net> This file is part of libdcp. @@ -31,16 +31,19 @@ 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; @@ -49,6 +52,7 @@ using std::dynamic_pointer_cast; 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>()) @@ -56,6 +60,7 @@ ReelClosedCaptionAsset::ReelClosedCaptionAsset (std::shared_ptr<SubtitleAsset> a } + ReelClosedCaptionAsset::ReelClosedCaptionAsset (std::shared_ptr<const cxml::Node> node) : ReelAsset (node) , ReelMXF (node) @@ -64,6 +69,7 @@ ReelClosedCaptionAsset::ReelClosedCaptionAsset (std::shared_ptr<const cxml::Node node->done (); } + string ReelClosedCaptionAsset::cpl_node_name (Standard standard) const { @@ -77,6 +83,7 @@ ReelClosedCaptionAsset::cpl_node_name (Standard standard) const DCP_ASSERT (false); } + pair<string, string> ReelClosedCaptionAsset::cpl_node_namespace (Standard standard) const { @@ -90,16 +97,18 @@ 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) { @@ -109,6 +118,7 @@ ReelClosedCaptionAsset::write_to_cpl (xmlpp::Node* node, Standard standard) cons return asset; } + bool ReelClosedCaptionAsset::equals (shared_ptr<const ReelClosedCaptionAsset> other, EqualityOptions opt, NoteHandler note) const { diff --git a/src/reel_closed_caption_asset.h b/src/reel_closed_caption_asset.h index 31122299..0aad8740 100644 --- a/src/reel_closed_caption_asset.h +++ b/src/reel_closed_caption_asset.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2012-2017 Carl Hetherington <cth@carlh.net> + Copyright (C) 2012-2021 Carl Hetherington <cth@carlh.net> This file is part of libdcp. @@ -31,13 +31,16 @@ 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" @@ -49,10 +52,12 @@ struct verify_invalid_language2; 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 { @@ -89,6 +94,8 @@ private: boost::optional<std::string> _language; }; + } + #endif diff --git a/src/reel_markers_asset.cc b/src/reel_markers_asset.cc index 1f9282fa..52151868 100644 --- a/src/reel_markers_asset.cc +++ b/src/reel_markers_asset.cc @@ -31,11 +31,13 @@ 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; @@ -43,12 +45,14 @@ using boost::optional; 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) { @@ -59,24 +63,28 @@ ReelMarkersAsset::ReelMarkersAsset (cxml::ConstNodePtr 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 { @@ -87,16 +95,17 @@ 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; diff --git a/src/reel_markers_asset.h b/src/reel_markers_asset.h index 46542614..5b33bbf2 100644 --- a/src/reel_markers_asset.h +++ b/src/reel_markers_asset.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2019 Carl Hetherington <cth@carlh.net> + Copyright (C) 2019-2021 Carl Hetherington <cth@carlh.net> This file is part of libdcp. @@ -31,12 +31,15 @@ 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: @@ -60,4 +63,5 @@ private: std::map<Marker, Time> _markers; }; + } diff --git a/src/reel_mono_picture_asset.cc b/src/reel_mono_picture_asset.cc index ec42919f..9c44ec20 100644 --- a/src/reel_mono_picture_asset.cc +++ b/src/reel_mono_picture_asset.cc @@ -1,5 +1,5 @@ /* - Copyright (C) 2014-2017 Carl Hetherington <cth@carlh.net> + Copyright (C) 2014-2021 Carl Hetherington <cth@carlh.net> This file is part of libdcp. @@ -31,30 +31,36 @@ 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 { diff --git a/src/reel_mono_picture_asset.h b/src/reel_mono_picture_asset.h index c996c762..9f1335be 100644 --- a/src/reel_mono_picture_asset.h +++ b/src/reel_mono_picture_asset.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2014-2019 Carl Hetherington <cth@carlh.net> + Copyright (C) 2014-2021 Carl Hetherington <cth@carlh.net> This file is part of libdcp. @@ -31,22 +31,28 @@ 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 { @@ -68,6 +74,8 @@ private: std::string cpl_node_name (Standard standard) const; }; + } + #endif diff --git a/src/reel_picture_asset.cc b/src/reel_picture_asset.cc index 2b3c3db0..8cdb9f44 100644 --- a/src/reel_picture_asset.cc +++ b/src/reel_picture_asset.cc @@ -1,5 +1,5 @@ /* - Copyright (C) 2014-2016 Carl Hetherington <cth@carlh.net> + Copyright (C) 2014-2021 Carl Hetherington <cth@carlh.net> This file is part of libdcp. @@ -31,10 +31,12 @@ 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" @@ -45,6 +47,7 @@ #include <iomanip> #include <cmath> + using std::bad_cast; using std::string; using std::shared_ptr; @@ -52,6 +55,7 @@ using std::dynamic_pointer_cast; 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()) @@ -61,6 +65,7 @@ ReelPictureAsset::ReelPictureAsset (shared_ptr<PictureAsset> asset, int64_t entr } + ReelPictureAsset::ReelPictureAsset (shared_ptr<const cxml::Node> node) : ReelAsset (node) , ReelMXF (node) @@ -79,10 +84,11 @@ ReelPictureAsset::ReelPictureAsset (shared_ptr<const cxml::Node> 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) { @@ -117,12 +123,14 @@ ReelPictureAsset::write_to_cpl (xmlpp::Node* node, Standard standard) const return asset; } + string ReelPictureAsset::key_type () const { return "MDIK"; } + bool ReelPictureAsset::equals (shared_ptr<const ReelPictureAsset> other, EqualityOptions opt, NoteHandler note) const { @@ -133,7 +141,7 @@ ReelPictureAsset::equals (shared_ptr<const ReelPictureAsset> other, EqualityOpti 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; } diff --git a/src/reel_picture_asset.h b/src/reel_picture_asset.h index a1f92628..12c23717 100644 --- a/src/reel_picture_asset.h +++ b/src/reel_picture_asset.h @@ -31,21 +31,26 @@ 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 { @@ -89,6 +94,8 @@ private: Fraction _screen_aspect_ratio; }; + } + #endif diff --git a/src/reel_sound_asset.cc b/src/reel_sound_asset.cc index 52095999..d3cc41d1 100644 --- a/src/reel_sound_asset.cc +++ b/src/reel_sound_asset.cc @@ -1,5 +1,5 @@ /* - Copyright (C) 2014-2015 Carl Hetherington <cth@carlh.net> + Copyright (C) 2014-2021 Carl Hetherington <cth@carlh.net> This file is part of libdcp. @@ -31,19 +31,23 @@ 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()) @@ -51,6 +55,7 @@ ReelSoundAsset::ReelSoundAsset (shared_ptr<SoundAsset> asset, int64_t entry_poin } + ReelSoundAsset::ReelSoundAsset (shared_ptr<const cxml::Node> node) : ReelAsset (node) , ReelMXF (node) @@ -59,26 +64,30 @@ ReelSoundAsset::ReelSoundAsset (shared_ptr<const cxml::Node> 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 { diff --git a/src/reel_sound_asset.h b/src/reel_sound_asset.h index cbc667e5..931bbc1e 100644 --- a/src/reel_sound_asset.h +++ b/src/reel_sound_asset.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2014-2019 Carl Hetherington <cth@carlh.net> + Copyright (C) 2014-2021 Carl Hetherington <cth@carlh.net> This file is part of libdcp. @@ -31,20 +31,24 @@ 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 { @@ -70,4 +74,5 @@ private: std::string cpl_node_name (Standard standard) const; }; + } diff --git a/src/reel_stereo_picture_asset.cc b/src/reel_stereo_picture_asset.cc index 958f8393..5bf4756c 100644 --- a/src/reel_stereo_picture_asset.cc +++ b/src/reel_stereo_picture_asset.cc @@ -1,5 +1,5 @@ /* - Copyright (C) 2014-2019 Carl Hetherington <cth@carlh.net> + Copyright (C) 2014-2021 Carl Hetherington <cth@carlh.net> This file is part of libdcp. @@ -31,46 +31,53 @@ 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); diff --git a/src/reel_stereo_picture_asset.h b/src/reel_stereo_picture_asset.h index b343626f..7e603108 100644 --- a/src/reel_stereo_picture_asset.h +++ b/src/reel_stereo_picture_asset.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2014-2019 Carl Hetherington <cth@carlh.net> + Copyright (C) 2014-2021 Carl Hetherington <cth@carlh.net> This file is part of libdcp. @@ -31,22 +31,28 @@ 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 { @@ -69,6 +75,8 @@ private: std::pair<std::string, std::string> cpl_node_attribute (Standard standard) const; }; + } + #endif diff --git a/src/reel_subtitle_asset.cc b/src/reel_subtitle_asset.cc index 029c8cb0..3a531962 100644 --- a/src/reel_subtitle_asset.cc +++ b/src/reel_subtitle_asset.cc @@ -1,5 +1,5 @@ /* - Copyright (C) 2012-2020 Carl Hetherington <cth@carlh.net> + Copyright (C) 2012-2021 Carl Hetherington <cth@carlh.net> This file is part of libdcp. @@ -31,22 +31,26 @@ 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>()) @@ -54,6 +58,7 @@ ReelSubtitleAsset::ReelSubtitleAsset (std::shared_ptr<SubtitleAsset> asset, Frac } + ReelSubtitleAsset::ReelSubtitleAsset (std::shared_ptr<const cxml::Node> node) : ReelAsset (node) , ReelMXF (node) @@ -62,22 +67,25 @@ ReelSubtitleAsset::ReelSubtitleAsset (std::shared_ptr<const cxml::Node> 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); @@ -85,6 +93,7 @@ ReelSubtitleAsset::write_to_cpl (xmlpp::Node* node, Standard standard) const return asset; } + bool ReelSubtitleAsset::equals (shared_ptr<const ReelSubtitleAsset> other, EqualityOptions opt, NoteHandler note) const { diff --git a/src/reel_subtitle_asset.h b/src/reel_subtitle_asset.h index d1fb3fef..93124140 100644 --- a/src/reel_subtitle_asset.h +++ b/src/reel_subtitle_asset.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2012-2020 Carl Hetherington <cth@carlh.net> + Copyright (C) 2012-2021 Carl Hetherington <cth@carlh.net> This file is part of libdcp. @@ -31,26 +31,33 @@ 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 { @@ -84,6 +91,8 @@ private: boost::optional<std::string> _language; }; + } + #endif diff --git a/src/rgb_xyz.cc b/src/rgb_xyz.cc index 4b3a5620..a5fd2a24 100644 --- a/src/rgb_xyz.cc +++ b/src/rgb_xyz.cc @@ -1,5 +1,5 @@ /* - Copyright (C) 2013-2015 Carl Hetherington <cth@carlh.net> + Copyright (C) 2013-2021 Carl Hetherington <cth@carlh.net> This file is part of libdcp. @@ -31,38 +31,28 @@ 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, @@ -139,15 +129,7 @@ dcp::xyz_to_rgba ( } } -/** 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, @@ -243,9 +225,6 @@ dcp::xyz_to_rgb ( } } -/** @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) { @@ -272,12 +251,7 @@ 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, @@ -287,7 +261,7 @@ dcp::rgb_to_xyz ( optional<NoteHandler> note ) { - shared_ptr<OpenJPEGImage> xyz (new OpenJPEGImage (size)); + auto xyz = make_shared<OpenJPEGImage>(size); struct { double r, g, b; @@ -297,8 +271,8 @@ dcp::rgb_to_xyz ( 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]; @@ -309,7 +283,7 @@ dcp::rgb_to_xyz ( 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) */ diff --git a/src/rgb_xyz.h b/src/rgb_xyz.h index 60df612c..eb1b5ac8 100644 --- a/src/rgb_xyz.h +++ b/src/rgb_xyz.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2013-2015 Carl Hetherington <cth@carlh.net> + Copyright (C) 2013-2021 Carl Hetherington <cth@carlh.net> This file is part of libdcp. @@ -31,17 +31,36 @@ 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, @@ -49,6 +68,16 @@ extern void xyz_to_rgba ( 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, @@ -57,6 +86,13 @@ extern void xyz_to_rgb ( 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, @@ -65,6 +101,10 @@ extern std::shared_ptr<OpenJPEGImage> rgb_to_xyz ( 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); } diff --git a/src/s_gamut3_transfer_function.cc b/src/s_gamut3_transfer_function.cc index 599028b4..edfbe2ad 100644 --- a/src/s_gamut3_transfer_function.cc +++ b/src/s_gamut3_transfer_function.cc @@ -1,5 +1,5 @@ /* - Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net> + Copyright (C) 2012-2021 Carl Hetherington <cth@carlh.net> This file is part of libdcp. @@ -31,18 +31,22 @@ 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 { @@ -50,7 +54,7 @@ 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 { @@ -59,7 +63,7 @@ SGamut3TransferFunction::make_lut (int bit_depth, bool inverse) const } } 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 { @@ -70,9 +74,10 @@ SGamut3TransferFunction::make_lut (int bit_depth, bool inverse) const 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); } diff --git a/src/s_gamut3_transfer_function.h b/src/s_gamut3_transfer_function.h index 3f83da87..88a6a65a 100644 --- a/src/s_gamut3_transfer_function.h +++ b/src/s_gamut3_transfer_function.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2016 Carl Hetherington <cth@carlh.net> + Copyright (C) 2016-2021 Carl Hetherington <cth@carlh.net> This file is part of libdcp. @@ -31,14 +31,18 @@ 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: @@ -48,4 +52,5 @@ protected: double * make_lut (int bit_depth, bool inverse) const; }; + } diff --git a/src/smpte_load_font_node.cc b/src/smpte_load_font_node.cc index 4d206784..d629b3b7 100644 --- a/src/smpte_load_font_node.cc +++ b/src/smpte_load_font_node.cc @@ -1,5 +1,5 @@ /* - Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net> + Copyright (C) 2012-2021 Carl Hetherington <cth@carlh.net> This file is part of libdcp. @@ -31,14 +31,22 @@ 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_) @@ -46,6 +54,7 @@ SMPTELoadFontNode::SMPTELoadFontNode (string id, string urn_) } + SMPTELoadFontNode::SMPTELoadFontNode (shared_ptr<const cxml::Node> node) : LoadFontNode (node->string_attribute ("ID")) , urn (remove_urn_uuid (node->content())) @@ -53,12 +62,14 @@ SMPTELoadFontNode::SMPTELoadFontNode (shared_ptr<const cxml::Node> node) } + 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) { diff --git a/src/smpte_load_font_node.h b/src/smpte_load_font_node.h index c310246d..7109e98b 100644 --- a/src/smpte_load_font_node.h +++ b/src/smpte_load_font_node.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2012-2015 Carl Hetherington <cth@carlh.net> + Copyright (C) 2012-2021 Carl Hetherington <cth@carlh.net> This file is part of libdcp. @@ -31,22 +31,27 @@ 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 { @@ -58,7 +63,9 @@ public: std::string urn; }; + bool operator== (SMPTELoadFontNode const & a, SMPTELoadFontNode const & b); bool operator!= (SMPTELoadFontNode const & a, SMPTELoadFontNode const & b); + } diff --git a/src/smpte_subtitle_asset.cc b/src/smpte_subtitle_asset.cc index 2c53cbb3..15a366ba 100644 --- a/src/smpte_subtitle_asset.cc +++ b/src/smpte_subtitle_asset.cc @@ -1,5 +1,5 @@ /* - Copyright (C) 2012-2019 Carl Hetherington <cth@carlh.net> + Copyright (C) 2012-2021 Carl Hetherington <cth@carlh.net> This file is part of libdcp. @@ -31,10 +31,12 @@ 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" @@ -51,6 +53,7 @@ #include <libxml++/libxml++.h> #include <boost/algorithm/string.hpp> + using std::string; using std::list; using std::vector; @@ -65,33 +68,32 @@ using boost::optional; 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); @@ -101,13 +103,13 @@ SMPTESubtitleAsset::SMPTESubtitleAsset (boost::filesystem::path file) 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")); @@ -116,7 +118,7 @@ SMPTESubtitleAsset::SMPTESubtitleAsset (boost::filesystem::path file) 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() ) ) ); @@ -152,6 +154,7 @@ SMPTESubtitleAsset::SMPTESubtitleAsset (boost::filesystem::path file) } } + void SMPTESubtitleAsset::parse_xml (shared_ptr<cxml::Document> xml) { @@ -178,7 +181,7 @@ 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 */ @@ -195,6 +198,7 @@ SMPTESubtitleAsset::parse_xml (shared_ptr<cxml::Document> xml) _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) { @@ -213,7 +217,7 @@ SMPTESubtitleAsset::read_mxf_descriptor (shared_ptr<ASDCP::TimedText::MXFReader> 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()); @@ -248,17 +252,17 @@ SMPTESubtitleAsset::read_mxf_descriptor (shared_ptr<ASDCP::TimedText::MXFReader> } } - /* 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); @@ -284,35 +288,38 @@ SMPTESubtitleAsset::set_key (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"); @@ -345,7 +352,7 @@ SMPTESubtitleAsset::xml_as_string () const return doc.write_to_string ("UTF-8"); } -/** Write this content to a MXF file */ + void SMPTESubtitleAsset::write (boost::filesystem::path p) const { @@ -422,7 +429,7 @@ 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)); } } @@ -455,7 +462,7 @@ SMPTESubtitleAsset::equals (shared_ptr<const Asset> other_asset, EqualityOptions 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; @@ -526,14 +533,16 @@ SMPTESubtitleAsset::equals (shared_ptr<const Asset> other_asset, EqualityOptions 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) { diff --git a/src/smpte_subtitle_asset.h b/src/smpte_subtitle_asset.h index 12eb58db..1521bf35 100644 --- a/src/smpte_subtitle_asset.h +++ b/src/smpte_subtitle_asset.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2012-2020 Carl Hetherington <cth@carlh.net> + Copyright (C) 2012-2021 Carl Hetherington <cth@carlh.net> This file is part of libdcp. @@ -31,10 +31,12 @@ 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" @@ -42,28 +44,34 @@ #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); @@ -76,7 +84,10 @@ public: 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); @@ -114,7 +125,7 @@ public: } /** @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; @@ -132,7 +143,7 @@ public: return _annotation_text; } - /** @return file creation time and date */ + /** @return file issue time and date */ LocalTime issue_date () const { return _issue_date; } @@ -185,7 +196,7 @@ private: /** 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, @@ -196,7 +207,7 @@ private: 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; @@ -206,4 +217,5 @@ private: std::string _xml_id; }; + } diff --git a/src/sound_asset.cc b/src/sound_asset.cc index 9d42e76d..1c0a181f 100644 --- a/src/sound_asset.cc +++ b/src/sound_asset.cc @@ -1,5 +1,5 @@ /* - Copyright (C) 2012-2020 Carl Hetherington <cth@carlh.net> + Copyright (C) 2012-2021 Carl Hetherington <cth@carlh.net> This file is part of libdcp. @@ -31,10 +31,12 @@ 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" @@ -50,6 +52,7 @@ #include <boost/filesystem.hpp> #include <stdexcept> + using std::string; using std::vector; using std::list; @@ -67,14 +70,14 @@ SoundAsset::SoundAsset (boost::filesystem::path file) , _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; @@ -84,12 +87,12 @@ SoundAsset::SoundAsset (boost::filesystem::path file) _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) ); @@ -105,10 +108,10 @@ SoundAsset::SoundAsset (boost::filesystem::path file) _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()) @@ -116,28 +119,29 @@ SoundAsset::SoundAsset (Fraction edit_rate, int sampling_rate, int channels, Lan } + 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")); } @@ -185,15 +189,15 @@ SoundAsset::equals (shared_ptr<const Asset> other, EqualityOptions opt, NoteHand /* 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)); @@ -201,7 +205,7 @@ SoundAsset::equals (shared_ptr<const Asset> other, EqualityOptions opt, NoteHand } 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) { @@ -216,6 +220,7 @@ SoundAsset::equals (shared_ptr<const Asset> other, EqualityOptions opt, NoteHand return true; } + shared_ptr<SoundAssetWriter> SoundAsset::start_write (boost::filesystem::path file, vector<Channel> active_channels, bool atmos_sync) { @@ -226,12 +231,14 @@ SoundAsset::start_write (boost::filesystem::path file, vector<Channel> active_ch 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) { @@ -245,10 +252,11 @@ 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); } diff --git a/src/sound_asset.h b/src/sound_asset.h index cc8f2ce0..e238de46 100644 --- a/src/sound_asset.h +++ b/src/sound_asset.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2012-2020 Carl Hetherington <cth@carlh.net> + Copyright (C) 2012-2021 Carl Hetherington <cth@carlh.net> This file is part of libdcp. @@ -31,13 +31,16 @@ 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" @@ -50,6 +53,7 @@ namespace dcp { 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 ); @@ -58,8 +62,10 @@ extern std::shared_ptr<dcp::SoundAsset> simple_sound ( namespace dcp { + class SoundAssetWriter; + /** @class SoundAsset * @brief Representation of a sound asset */ @@ -117,12 +123,14 @@ private: /** 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 diff --git a/src/sound_asset_reader.h b/src/sound_asset_reader.h index 8ec4e59f..e0715040 100644 --- a/src/sound_asset_reader.h +++ b/src/sound_asset_reader.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2016 Carl Hetherington <cth@carlh.net> + Copyright (C) 2016-2021 Carl Hetherington <cth@carlh.net> This file is part of libdcp. @@ -31,11 +31,20 @@ 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; + } diff --git a/src/sound_asset_writer.cc b/src/sound_asset_writer.cc index 5c5bcdec..f54c960e 100644 --- a/src/sound_asset_writer.cc +++ b/src/sound_asset_writer.cc @@ -31,6 +31,12 @@ 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" @@ -42,6 +48,7 @@ #include <asdcp/Metadata.h> #include <iostream> + using std::min; using std::max; using std::cout; @@ -58,13 +65,12 @@ struct SoundAssetWriter::ASDCPState 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); @@ -74,7 +80,7 @@ SoundAssetWriter::SoundAssetWriter (SoundAsset* asset, boost::filesystem::path f _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; @@ -108,21 +114,21 @@ SoundAssetWriter::SoundAssetWriter (SoundAsset* asset, boost::filesystem::path f 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(); @@ -142,7 +148,7 @@ SoundAssetWriter::start () 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; @@ -160,9 +166,6 @@ SoundAssetWriter::start () } -/** @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) { @@ -202,7 +205,7 @@ 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())) { @@ -216,9 +219,9 @@ SoundAssetWriter::write (float const * const * data, int frames) 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; @@ -237,9 +240,9 @@ SoundAssetWriter::finalize () } 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)))); } } @@ -261,7 +264,7 @@ SoundAssetWriter::create_sync_packets () 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; diff --git a/src/sound_asset_writer.h b/src/sound_asset_writer.h index f1cdf419..d2eba024 100644 --- a/src/sound_asset_writer.h +++ b/src/sound_asset_writer.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2012-2020 Carl Hetherington <cth@carlh.net> + Copyright (C) 2012-2021 Carl Hetherington <cth@carlh.net> This file is part of libdcp. @@ -31,10 +31,12 @@ 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" @@ -49,8 +51,10 @@ struct sync_test1; namespace dcp { + class SoundAsset; + /** @class SoundAssetWriter * @brief A helper class for writing to SoundAssets. * @@ -63,7 +67,11 @@ class SoundAsset; 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: @@ -83,13 +91,13 @@ 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; diff --git a/src/sound_frame.cc b/src/sound_frame.cc index 821a8866..9c8087c2 100644 --- a/src/sound_frame.cc +++ b/src/sound_frame.cc @@ -1,5 +1,5 @@ /* - Copyright (C) 2012-2017 Carl Hetherington <cth@carlh.net> + Copyright (C) 2012-2021 Carl Hetherington <cth@carlh.net> This file is part of libdcp. @@ -31,13 +31,21 @@ 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) { @@ -46,6 +54,7 @@ SoundFrame::SoundFrame (ASDCP::PCM::MXFReader* reader, int n, std::shared_ptr<co _channels = desc.ChannelCount; } + int32_t SoundFrame::get (int channel, int frame) const { @@ -54,12 +63,14 @@ 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 { diff --git a/src/sound_frame.h b/src/sound_frame.h index 096bc1b3..85082299 100644 --- a/src/sound_frame.h +++ b/src/sound_frame.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2012-2017 Carl Hetherington <cth@carlh.net> + Copyright (C) 2012-2021 Carl Hetherington <cth@carlh.net> This file is part of libdcp. @@ -31,18 +31,23 @@ 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: @@ -52,9 +57,11 @@ public: int32_t get (int channel, int sample) const; private: - int _channels; + int _channels = 0; }; + } + #endif diff --git a/src/stereo_picture_asset.cc b/src/stereo_picture_asset.cc index 231af538..7e3f6f63 100644 --- a/src/stereo_picture_asset.cc +++ b/src/stereo_picture_asset.cc @@ -1,5 +1,5 @@ /* - Copyright (C) 2012-2016 Carl Hetherington <cth@carlh.net> + Copyright (C) 2012-2021 Carl Hetherington <cth@carlh.net> This file is part of libdcp. @@ -31,6 +31,12 @@ 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" @@ -39,6 +45,7 @@ #include "dcp_assert.h" #include <asdcp/AS_DCP.h> + using std::string; using std::pair; using std::make_pair; @@ -46,60 +53,65 @@ using std::shared_ptr; 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)); @@ -118,11 +130,11 @@ StereoPictureAsset::equals (shared_ptr<const Asset> other, EqualityOptions opt, 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; diff --git a/src/stereo_picture_asset.h b/src/stereo_picture_asset.h index e0302758..897ed4a4 100644 --- a/src/stereo_picture_asset.h +++ b/src/stereo_picture_asset.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2012-2015 Carl Hetherington <cth@carlh.net> + Copyright (C) 2012-2021 Carl Hetherington <cth@carlh.net> This file is part of libdcp. @@ -31,15 +31,26 @@ 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: @@ -57,6 +68,8 @@ public: ) const; }; + } + #endif diff --git a/src/stereo_picture_asset_reader.h b/src/stereo_picture_asset_reader.h index f82443e7..9cb05263 100644 --- a/src/stereo_picture_asset_reader.h +++ b/src/stereo_picture_asset_reader.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2016 Carl Hetherington <cth@carlh.net> + Copyright (C) 2016-2021 Carl Hetherington <cth@carlh.net> This file is part of libdcp. @@ -31,16 +31,27 @@ 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 diff --git a/src/stereo_picture_asset_writer.cc b/src/stereo_picture_asset_writer.cc index 6245873d..e02e8360 100644 --- a/src/stereo_picture_asset_writer.cc +++ b/src/stereo_picture_asset_writer.cc @@ -1,5 +1,5 @@ /* - Copyright (C) 2012-2016 Carl Hetherington <cth@carlh.net> + Copyright (C) 2012-2021 Carl Hetherington <cth@carlh.net> This file is part of libdcp. @@ -31,6 +31,12 @@ 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" @@ -39,25 +45,29 @@ #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) { @@ -65,10 +75,7 @@ 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) { @@ -85,7 +92,7 @@ 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(), @@ -106,15 +113,16 @@ StereoPictureAssetWriter::write (uint8_t const * data, int size) 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; @@ -123,13 +131,14 @@ StereoPictureAssetWriter::fake_write (int size) } } + 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)); } } diff --git a/src/stereo_picture_asset_writer.h b/src/stereo_picture_asset_writer.h index d4dfa0f6..cf3e2a4e 100644 --- a/src/stereo_picture_asset_writer.h +++ b/src/stereo_picture_asset_writer.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2012-2016 Carl Hetherington <cth@carlh.net> + Copyright (C) 2012-2021 Carl Hetherington <cth@carlh.net> This file is part of libdcp. @@ -31,16 +31,22 @@ 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. * @@ -75,7 +81,8 @@ private: struct ASDCPState; std::shared_ptr<ASDCPState> _state; - dcp::Eye _next_eye; + dcp::Eye _next_eye = Eye::LEFT; }; + } diff --git a/src/subtitle.cc b/src/subtitle.cc index 6e3a2911..9d82a128 100644 --- a/src/subtitle.cc +++ b/src/subtitle.cc @@ -1,5 +1,5 @@ /* - Copyright (C) 2012-2018 Carl Hetherington <cth@carlh.net> + Copyright (C) 2012-2021 Carl Hetherington <cth@carlh.net> This file is part of libdcp. @@ -31,11 +31,19 @@ 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, diff --git a/src/subtitle.h b/src/subtitle.h index 17e3f92f..8beca192 100644 --- a/src/subtitle.h +++ b/src/subtitle.h @@ -31,17 +31,22 @@ 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: @@ -131,17 +136,19 @@ protected: /** 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 diff --git a/src/subtitle_asset.cc b/src/subtitle_asset.cc index 52ef7ac2..99673da9 100644 --- a/src/subtitle_asset.cc +++ b/src/subtitle_asset.cc @@ -31,6 +31,12 @@ 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" @@ -49,6 +55,7 @@ #include <boost/lexical_cast.hpp> #include <boost/shared_array.hpp> + using std::dynamic_pointer_cast; using std::string; using std::cout; @@ -62,53 +69,59 @@ using boost::optional; 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> (); } @@ -118,6 +131,7 @@ optional_number_attribute (xmlpp::Element const * node, string name) return raw_convert<T> (t); } + SubtitleAsset::ParseState SubtitleAsset::font_node_state (xmlpp::Element const * node, Standard standard) const { @@ -137,11 +151,11 @@ SubtitleAsset::font_node_state (xmlpp::Element const * node, Standard standard) } 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 ()); } @@ -156,7 +170,7 @@ SubtitleAsset::font_node_state (xmlpp::Element const * node, Standard standard) 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"); } @@ -164,7 +178,7 @@ SubtitleAsset::position_align (SubtitleAsset::ParseState& ps, xmlpp::Element con 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"); } @@ -172,7 +186,7 @@ SubtitleAsset::position_align (SubtitleAsset::ParseState& ps, xmlpp::Element con 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"); } @@ -180,7 +194,7 @@ SubtitleAsset::position_align (SubtitleAsset::ParseState& ps, xmlpp::Element con 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"); } @@ -190,6 +204,7 @@ SubtitleAsset::position_align (SubtitleAsset::ParseState& ps, xmlpp::Element con } + SubtitleAsset::ParseState SubtitleAsset::text_node_state (xmlpp::Element const * node) const { @@ -197,7 +212,7 @@ 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 ()); } @@ -207,6 +222,7 @@ SubtitleAsset::text_node_state (xmlpp::Element const * node) const return ps; } + SubtitleAsset::ParseState SubtitleAsset::image_node_state (xmlpp::Element const * node) const { @@ -219,6 +235,7 @@ 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 { @@ -230,10 +247,11 @@ SubtitleAsset::subtitle_node_state (xmlpp::Element const * node, optional<int> t 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 ()) { @@ -251,6 +269,7 @@ SubtitleAsset::fade_time (xmlpp::Element const * node, string name, optional<int return t; } + void SubtitleAsset::parse_subtitles (xmlpp::Element const * node, vector<ParseState>& state, optional<int> tcr, Standard standard) { @@ -268,13 +287,12 @@ SubtitleAsset::parse_subtitles (xmlpp::Element const * node, vector<ParseState>& 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); } @@ -283,6 +301,7 @@ SubtitleAsset::parse_subtitles (xmlpp::Element const * node, vector<ParseState>& state.pop_back (); } + void SubtitleAsset::maybe_add_subtitle (string text, vector<ParseState> const & parse_state, Standard standard) { @@ -361,47 +380,43 @@ SubtitleAsset::maybe_add_subtitle (string text, vector<ParseState> const & parse 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; @@ -460,6 +475,7 @@ SubtitleAsset::add (shared_ptr<Subtitle> s) _subtitles.push_back (s); } + Time SubtitleAsset::latest_subtitle_out () const { @@ -473,6 +489,7 @@ SubtitleAsset::latest_subtitle_out () const return t; } + bool SubtitleAsset::equals (shared_ptr<const Asset> other_asset, EqualityOptions options, NoteHandler note) const { @@ -494,10 +511,10 @@ SubtitleAsset::equals (shared_ptr<const Asset> other_asset, EqualityOptions opti 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"); @@ -520,6 +537,7 @@ SubtitleAsset::equals (shared_ptr<const Asset> other_asset, EqualityOptions opti return true; } + struct SubtitleSorter { bool operator() (shared_ptr<Subtitle> a, shared_ptr<Subtitle> b) { @@ -530,6 +548,7 @@ struct SubtitleSorter } }; + void SubtitleAsset::pull_fonts (shared_ptr<order::Part> part) { @@ -590,6 +609,7 @@ 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. */ @@ -657,7 +677,7 @@ SubtitleAsset::subtitles_as_xml (xmlpp::Element* xml_root, int time_code_rate, S 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 ( @@ -680,6 +700,7 @@ SubtitleAsset::subtitles_as_xml (xmlpp::Element* xml_root, int time_code_rate, S root->write_xml (xml_root, context); } + map<string, ArrayData> SubtitleAsset::font_data () const { diff --git a/src/subtitle_asset.h b/src/subtitle_asset.h index 7502ad33..0afce3d0 100644 --- a/src/subtitle_asset.h +++ b/src/subtitle_asset.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2012-2015 Carl Hetherington <cth@carlh.net> + Copyright (C) 2012-2021 Carl Hetherington <cth@carlh.net> This file is part of libdcp. @@ -31,6 +31,12 @@ 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 @@ -43,18 +49,21 @@ #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; @@ -64,13 +73,15 @@ class SubtitleNode; 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. @@ -195,6 +206,8 @@ private: static void pull_fonts (std::shared_ptr<order::Part> part); }; + } + #endif diff --git a/src/subtitle_asset_internal.cc b/src/subtitle_asset_internal.cc index d7b16cbd..f1674789 100644 --- a/src/subtitle_asset_internal.cc +++ b/src/subtitle_asset_internal.cc @@ -1,5 +1,5 @@ /* - Copyright (C) 2012-2018 Carl Hetherington <cth@carlh.net> + Copyright (C) 2012-2021 Carl Hetherington <cth@carlh.net> This file is part of libdcp. @@ -31,22 +31,31 @@ 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()) { @@ -71,6 +80,7 @@ order::Font::Font (shared_ptr<SubtitleString> s, Standard standard) _values["Weight"] = s->bold() ? "bold" : "normal"; } + xmlpp::Element* order::Font::as_xml (xmlpp::Element* parent, Context& context) const { @@ -81,6 +91,7 @@ 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. */ @@ -89,42 +100,46 @@ order::Font::take_intersection (Font 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 { @@ -132,6 +147,7 @@ order::String::as_xml (xmlpp::Element* parent, Context &) const return 0; } + void order::Part::write_xml (xmlpp::Element* parent, order::Context& context) const { @@ -146,6 +162,7 @@ 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) { @@ -186,10 +203,11 @@ position_align (xmlpp::Element* e, order::Context& context, HAlign h_align, floa } } + 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); @@ -203,10 +221,11 @@ order::Text::as_xml (xmlpp::Element* parent, Context& context) const 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)); @@ -220,22 +239,25 @@ order::Subtitle::as_xml (xmlpp::Element* parent, Context& context) const 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) { diff --git a/src/subtitle_asset_internal.h b/src/subtitle_asset_internal.h index 0af16238..c7037dcf 100644 --- a/src/subtitle_asset_internal.h +++ b/src/subtitle_asset_internal.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2012-2016 Carl Hetherington <cth@carlh.net> + Copyright (C) 2012-2021 Carl Hetherington <cth@carlh.net> This file is part of libdcp. @@ -31,6 +31,12 @@ 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 @@ -41,18 +47,23 @@ #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; @@ -62,6 +73,7 @@ struct Context int spot_number; }; + class Font { public: @@ -87,6 +99,7 @@ private: std::map<std::string, std::string> _values; }; + class Part { public: @@ -109,6 +122,7 @@ public: std::vector<std::shared_ptr<Part>> children; }; + class String : public Part { public: @@ -122,6 +136,7 @@ public: std::string text; }; + class Text : public Part { public: @@ -144,6 +159,7 @@ private: Direction _direction; }; + class Subtitle : public Part { public: @@ -164,6 +180,7 @@ private: Time _fade_down; }; + class Image : public Part { public: @@ -188,8 +205,9 @@ private: float _v_position; }; -} } +} + #endif |
