From fe99eae4b95c5fcf2f3730efad4a18d0cb5c29bc Mon Sep 17 00:00:00 2001 From: Carl Hetherington Date: Fri, 5 Jun 2015 00:05:32 +0100 Subject: MXF -> Asset in lots of places. --- src/asset_writer.cc | 68 +++++++++++++ src/asset_writer.h | 67 ++++++++++++ src/dcp.cc | 14 +-- src/decrypted_kdm.h | 8 +- src/key.h | 2 +- src/mono_picture_asset.cc | 138 +++++++++++++++++++++++++ src/mono_picture_asset.h | 62 ++++++++++++ src/mono_picture_asset_writer.cc | 111 ++++++++++++++++++++ src/mono_picture_asset_writer.h | 69 +++++++++++++ src/mono_picture_frame.cc | 8 +- src/mono_picture_frame.h | 2 +- src/mono_picture_mxf.cc | 138 ------------------------- src/mono_picture_mxf.h | 62 ------------ src/mono_picture_mxf_writer.cc | 111 -------------------- src/mono_picture_mxf_writer.h | 69 ------------- src/mxf.h | 4 +- src/mxf_writer.cc | 68 ------------- src/mxf_writer.h | 67 ------------ src/picture_asset.cc | 202 +++++++++++++++++++++++++++++++++++++ src/picture_asset.h | 126 +++++++++++++++++++++++ src/picture_asset_writer.cc | 42 ++++++++ src/picture_asset_writer.h | 84 +++++++++++++++ src/picture_asset_writer_common.cc | 64 ++++++++++++ src/picture_mxf.cc | 202 ------------------------------------- src/picture_mxf.h | 126 ----------------------- src/picture_mxf_writer.cc | 42 -------- src/picture_mxf_writer.h | 84 --------------- src/picture_mxf_writer_common.cc | 64 ------------ src/reel.cc | 18 ++-- src/reel_asset.cc | 14 +-- src/reel_asset.h | 6 +- src/reel_mono_picture_asset.cc | 8 +- src/reel_mono_picture_asset.h | 8 +- src/reel_mxf_asset.h | 2 +- src/reel_picture_asset.cc | 4 +- src/reel_picture_asset.h | 12 +-- src/reel_sound_asset.cc | 2 +- src/reel_sound_asset.h | 16 +-- src/reel_stereo_picture_asset.cc | 4 +- src/reel_stereo_picture_asset.h | 4 +- src/reel_subtitle_asset.h | 2 +- src/sound_asset.cc | 180 +++++++++++++++++++++++++++++++++ src/sound_asset.h | 90 +++++++++++++++++ src/sound_asset_writer.cc | 121 ++++++++++++++++++++++ src/sound_asset_writer.h | 68 +++++++++++++ src/sound_frame.cc | 6 +- src/sound_frame.h | 2 +- src/sound_mxf.cc | 183 --------------------------------- src/sound_mxf.h | 90 ----------------- src/sound_mxf_writer.cc | 121 ---------------------- src/sound_mxf_writer.h | 68 ------------- src/stereo_picture_asset.cc | 140 +++++++++++++++++++++++++ src/stereo_picture_asset.h | 48 +++++++++ src/stereo_picture_asset_writer.cc | 123 ++++++++++++++++++++++ src/stereo_picture_asset_writer.h | 67 ++++++++++++ src/stereo_picture_frame.cc | 8 +- src/stereo_picture_frame.h | 2 +- src/stereo_picture_mxf.cc | 140 ------------------------- src/stereo_picture_mxf.h | 48 --------- src/stereo_picture_mxf_writer.cc | 123 ---------------------- src/stereo_picture_mxf_writer.h | 67 ------------ src/types.h | 3 - src/wscript | 32 +++--- 63 files changed, 1964 insertions(+), 1970 deletions(-) create mode 100644 src/asset_writer.cc create mode 100644 src/asset_writer.h create mode 100644 src/mono_picture_asset.cc create mode 100644 src/mono_picture_asset.h create mode 100644 src/mono_picture_asset_writer.cc create mode 100644 src/mono_picture_asset_writer.h delete mode 100644 src/mono_picture_mxf.cc delete mode 100644 src/mono_picture_mxf.h delete mode 100644 src/mono_picture_mxf_writer.cc delete mode 100644 src/mono_picture_mxf_writer.h delete mode 100644 src/mxf_writer.cc delete mode 100644 src/mxf_writer.h create mode 100644 src/picture_asset.cc create mode 100644 src/picture_asset.h create mode 100644 src/picture_asset_writer.cc create mode 100644 src/picture_asset_writer.h create mode 100644 src/picture_asset_writer_common.cc delete mode 100644 src/picture_mxf.cc delete mode 100644 src/picture_mxf.h delete mode 100644 src/picture_mxf_writer.cc delete mode 100644 src/picture_mxf_writer.h delete mode 100644 src/picture_mxf_writer_common.cc create mode 100644 src/sound_asset.cc create mode 100644 src/sound_asset.h create mode 100644 src/sound_asset_writer.cc create mode 100644 src/sound_asset_writer.h delete mode 100644 src/sound_mxf.cc delete mode 100644 src/sound_mxf.h delete mode 100644 src/sound_mxf_writer.cc delete mode 100644 src/sound_mxf_writer.h create mode 100644 src/stereo_picture_asset.cc create mode 100644 src/stereo_picture_asset.h create mode 100644 src/stereo_picture_asset_writer.cc create mode 100644 src/stereo_picture_asset_writer.h delete mode 100644 src/stereo_picture_mxf.cc delete mode 100644 src/stereo_picture_mxf.h delete mode 100644 src/stereo_picture_mxf_writer.cc delete mode 100644 src/stereo_picture_mxf_writer.h (limited to 'src') diff --git a/src/asset_writer.cc b/src/asset_writer.cc new file mode 100644 index 00000000..eb55feaf --- /dev/null +++ b/src/asset_writer.cc @@ -0,0 +1,68 @@ +/* + Copyright (C) 2012-2015 Carl Hetherington + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +/** @file src/asset_writer.h + * @brief AssetWriter class. + */ + +#include "asset_writer.h" +#include "mxf.h" +#include "dcp_assert.h" +#include "AS_DCP.h" +#include "KM_prng.h" + +using namespace dcp; + +/** Create an AssetWriter. + * @param mxf MXF that we are writing. + * @param file File to write to. + */ +AssetWriter::AssetWriter (MXF* mxf, boost::filesystem::path file) + : _mxf (mxf) + , _file (file) + , _frames_written (0) + , _finalized (false) + , _encryption_context (0) +{ + if (mxf->key ()) { + _encryption_context = new ASDCP::AESEncContext; + if (ASDCP_FAILURE (_encryption_context->InitKey (mxf->key()->value ()))) { + throw MiscError ("could not set up encryption context"); + } + + uint8_t cbc_buffer[ASDCP::CBC_BLOCK_SIZE]; + + Kumu::FortunaRNG rng; + if (ASDCP_FAILURE (_encryption_context->SetIVec (rng.FillRandom (cbc_buffer, ASDCP::CBC_BLOCK_SIZE)))) { + throw MiscError ("could not set up CBC initialization vector"); + } + } +} + +AssetWriter::~AssetWriter () +{ + delete _encryption_context; +} + +void +AssetWriter::finalize () +{ + DCP_ASSERT (!_finalized); + _finalized = true; +} diff --git a/src/asset_writer.h b/src/asset_writer.h new file mode 100644 index 00000000..31d2f7ae --- /dev/null +++ b/src/asset_writer.h @@ -0,0 +1,67 @@ +/* + Copyright (C) 2012-2015 Carl Hetherington + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +/** @file src/asset_writer.h + * @brief AssetWriter class. + */ + +#ifndef LIBDCP_ASSET_WRITER_H +#define LIBDCP_ASSET_WRITER_H + +#include + +namespace ASDCP { + class AESEncContext; +} + +namespace dcp { + +class MXF; + +/** @class AssetWriter + * @brief Parent class for classes which can write MXF-based assets. + * + * The AssetWriter lasts for the duration of the write and is then discarded. + * They can only be created by calling start_write() on an appropriate Asset object. + */ +class AssetWriter : public boost::noncopyable +{ +public: + virtual ~AssetWriter (); + virtual void finalize (); + +protected: + AssetWriter (MXF* mxf, boost::filesystem::path file); + + /** MXF that we are writing */ + MXF* _mxf; + /** File that we are writing to */ + boost::filesystem::path _file; + /** Number of `frames' written so far; the definition of a frame + * varies depending on the subclass. + */ + int64_t _frames_written; + /** true if finalize() has been called on this object */ + bool _finalized; + ASDCP::AESEncContext* _encryption_context; +}; + +} + +#endif diff --git a/src/dcp.cc b/src/dcp.cc index e1b632c6..abeafdfb 100644 --- a/src/dcp.cc +++ b/src/dcp.cc @@ -23,12 +23,12 @@ #include "raw_convert.h" #include "dcp.h" -#include "sound_mxf.h" -#include "picture_mxf.h" +#include "sound_asset.h" +#include "picture_asset.h" #include "interop_subtitle_asset.h" #include "smpte_subtitle_asset.h" -#include "mono_picture_mxf.h" -#include "stereo_picture_mxf.h" +#include "mono_picture_asset.h" +#include "stereo_picture_asset.h" #include "util.h" #include "metadata.h" #include "exceptions.h" @@ -149,14 +149,14 @@ DCP::read (bool keep_going, ReadErrors* errors) case ASDCP::ESS_MPEG2_VES: throw DCPReadError ("MPEG2 video essences are not supported"); case ASDCP::ESS_JPEG_2000: - _assets.push_back (shared_ptr (new MonoPictureMXF (path))); + _assets.push_back (shared_ptr (new MonoPictureAsset (path))); break; case ASDCP::ESS_PCM_24b_48k: case ASDCP::ESS_PCM_24b_96k: - _assets.push_back (shared_ptr (new SoundMXF (path))); + _assets.push_back (shared_ptr (new SoundAsset (path))); break; case ASDCP::ESS_JPEG_2000_S: - _assets.push_back (shared_ptr (new StereoPictureMXF (path))); + _assets.push_back (shared_ptr (new StereoPictureAsset (path))); break; case ASDCP::ESS_TIMED_TEXT: _assets.push_back (shared_ptr (new SMPTESubtitleAsset (path))); diff --git a/src/decrypted_kdm.h b/src/decrypted_kdm.h index 91b2f7d3..5ea67861 100644 --- a/src/decrypted_kdm.h +++ b/src/decrypted_kdm.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2013-2014 Carl Hetherington + Copyright (C) 2013-2015 Carl Hetherington This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -45,7 +45,7 @@ class CPL; * has been created (by some other means) ready for encryption later. * * A DecryptedKDM object can be created either from an EncryptedKDM and private key file, - * or from the details of the MXFs that the KDM should protect. + * or from the details of the assets that the KDM should protect. */ class DecryptedKDM { @@ -57,7 +57,7 @@ public: /** Construct a DecryptedKDM. * @param cpl CPL that the keys are for. - * @param key Key that was used to encrypt the MXFs. + * @param key Key that was used to encrypt the assets. * @param not_valid_before Start time for the KDM. * @param not_valid_after End time for the KDM. */ @@ -79,7 +79,7 @@ public: */ EncryptedKDM encrypt (boost::shared_ptr signer, Certificate recipient, Formulation formulation) const; - /** @return This KDM's (decrypted) keys, which could be used to decrypt MXFs. */ + /** @return This KDM's (decrypted) keys, which could be used to decrypt assets. */ std::list keys () const { return _keys; } diff --git a/src/key.h b/src/key.h index 248a2a95..9d16c8a1 100644 --- a/src/key.h +++ b/src/key.h @@ -30,7 +30,7 @@ namespace dcp { /** @class Key - * @brief A key for decrypting/encrypting MXFs. + * @brief A key for decrypting/encrypting assets. */ class Key { diff --git a/src/mono_picture_asset.cc b/src/mono_picture_asset.cc new file mode 100644 index 00000000..19210ce8 --- /dev/null +++ b/src/mono_picture_asset.cc @@ -0,0 +1,138 @@ +/* + Copyright (C) 2012-2014 Carl Hetherington + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#include "mono_picture_asset.h" +#include "mono_picture_asset_writer.h" +#include "AS_DCP.h" +#include "KM_fileio.h" +#include "exceptions.h" +#include "dcp_assert.h" +#include "mono_picture_frame.h" +#include "compose.hpp" + +using std::string; +using std::vector; +using boost::shared_ptr; +using boost::dynamic_pointer_cast; +using namespace dcp; + +MonoPictureAsset::MonoPictureAsset (boost::filesystem::path file) + : PictureAsset (file) +{ + ASDCP::JP2K::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)); + } + + ASDCP::JP2K::PictureDescriptor desc; + if (ASDCP_FAILURE (reader.FillPictureDescriptor (desc))) { + boost::throw_exception (DCPReadError ("could not read video MXF information")); + } + + read_picture_descriptor (desc); + + ASDCP::WriterInfo info; + if (ASDCP_FAILURE (reader.FillWriterInfo (info))) { + boost::throw_exception (DCPReadError ("could not read video MXF information")); + } + + _id = read_writer_info (info); +} + +MonoPictureAsset::MonoPictureAsset (Fraction edit_rate) + : PictureAsset (edit_rate) +{ + +} + +shared_ptr +MonoPictureAsset::get_frame (int n) const +{ + return shared_ptr (new MonoPictureFrame (_file, n, _decryption_context)); +} + +bool +MonoPictureAsset::equals (shared_ptr other, EqualityOptions opt, NoteHandler note) const +{ + if (!dynamic_pointer_cast (other)) { + return false; + } + + ASDCP::JP2K::MXFReader reader_A; + 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)); + } + + ASDCP::JP2K::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)); + } + + ASDCP::JP2K::PictureDescriptor desc_A; + if (ASDCP_FAILURE (reader_A.FillPictureDescriptor (desc_A))) { + boost::throw_exception (DCPReadError ("could not read video MXF information")); + } + ASDCP::JP2K::PictureDescriptor desc_B; + if (ASDCP_FAILURE (reader_B.FillPictureDescriptor (desc_B))) { + boost::throw_exception (DCPReadError ("could not read video MXF information")); + } + + if (!descriptor_equals (desc_A, desc_B, note)) { + return false; + } + + shared_ptr other_picture = dynamic_pointer_cast (other); + DCP_ASSERT (other_picture); + + for (int i = 0; i < _intrinsic_duration; ++i) { + if (i >= other_picture->intrinsic_duration()) { + return false; + } + + note (DCP_PROGRESS, String::compose ("Comparing video frame %1 of %2", i, _intrinsic_duration)); + shared_ptr frame_A = get_frame (i); + shared_ptr frame_B = other_picture->get_frame (i); + + if (!frame_buffer_equals ( + i, opt, note, + frame_A->j2k_data(), frame_A->j2k_size(), + frame_B->j2k_data(), frame_B->j2k_size() + )) { + return false; + } + } + + return true; +} + +shared_ptr +MonoPictureAsset::start_write (boost::filesystem::path file, Standard standard, bool overwrite) +{ + /* XXX: can't we use shared_ptr here? */ + return shared_ptr (new MonoPictureAssetWriter (this, file, standard, overwrite)); +} + +string +MonoPictureAsset::cpl_node_name () const +{ + return "MainPicture"; +} diff --git a/src/mono_picture_asset.h b/src/mono_picture_asset.h new file mode 100644 index 00000000..fc1e4f9c --- /dev/null +++ b/src/mono_picture_asset.h @@ -0,0 +1,62 @@ +/* + Copyright (C) 2012-2015 Carl Hetherington + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#ifndef LIBDCP_MONO_PICTURE_ASSET_H +#define LIBDCP_MONO_PICTURE_ASSET_H + +#include "picture_asset.h" + +namespace dcp { + +class MonoPictureAssetWriter; + +/** @class MonoPictureAsset + * @brief A 2D (monoscopic) picture asset. + */ +class MonoPictureAsset : public PictureAsset +{ +public: + /** Create a MonoPictureAsset by reading a file. + * @param file Asset file to read. + */ + MonoPictureAsset (boost::filesystem::path file); + + /** Create a MonoPictureAsset with a given edit rate. + * @param edit_rate Edit rate (i.e. frame rate) in frames per second. + */ + MonoPictureAsset (Fraction edit_rate); + + /** Start a progressive write to a MonoPictureAsset */ + boost::shared_ptr start_write (boost::filesystem::path, Standard standard, bool); + + bool equals ( + boost::shared_ptr other, + EqualityOptions opt, + NoteHandler note + ) const; + + boost::shared_ptr get_frame (int n) const; + +private: + std::string cpl_node_name () const; +}; + +} + +#endif diff --git a/src/mono_picture_asset_writer.cc b/src/mono_picture_asset_writer.cc new file mode 100644 index 00000000..0f09f8fe --- /dev/null +++ b/src/mono_picture_asset_writer.cc @@ -0,0 +1,111 @@ +/* + Copyright (C) 2012-2014 Carl Hetherington + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +/** @file src/mono_picture_asset_writer.cc + * @brief MonoPictureAssetWriter class + */ + +#include "AS_DCP.h" +#include "KM_fileio.h" +#include "mono_picture_asset_writer.h" +#include "exceptions.h" +#include "picture_asset.h" +#include "dcp_assert.h" + +#include "picture_asset_writer_common.cc" + +using std::istream; +using std::ostream; +using std::string; +using boost::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. + */ +MonoPictureAssetWriter::MonoPictureAssetWriter (PictureAsset* asset, boost::filesystem::path file, Standard standard, bool overwrite) + : PictureAssetWriter (asset, file, standard, overwrite) + , _state (new MonoPictureAssetWriter::ASDCPState) +{ + +} + +void +MonoPictureAssetWriter::start (uint8_t* data, int size) +{ + dcp::start (this, _state, _standard, _picture_asset, data, size); + _picture_asset->set_frame_rate (_picture_asset->edit_rate()); +} + +FrameInfo +MonoPictureAssetWriter::write (uint8_t* data, int size) +{ + DCP_ASSERT (!_finalized); + + if (!_started) { + start (data, size); + } + + 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, _encryption_context, 0, &hash); + if (ASDCP_FAILURE (r)) { + boost::throw_exception (MXFFileError ("error in writing video MXF", _file.string(), r)); + } + + ++_frames_written; + 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)); + } + + ++_frames_written; +} + +void +MonoPictureAssetWriter::finalize () +{ + Kumu::Result_t r = _state->mxf_writer.Finalize(); + if (ASDCP_FAILURE (r)) { + boost::throw_exception (MXFFileError ("error in finalizing video MXF", _file.string(), r)); + } + + _picture_asset->_intrinsic_duration = _frames_written; + PictureAssetWriter::finalize (); +} + diff --git a/src/mono_picture_asset_writer.h b/src/mono_picture_asset_writer.h new file mode 100644 index 00000000..6478c9bf --- /dev/null +++ b/src/mono_picture_asset_writer.h @@ -0,0 +1,69 @@ +/* + Copyright (C) 2012-2015 Carl Hetherington + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +/** @file src/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 +#include +#include +#include +#include + +namespace dcp { + +/** @class MonoPictureAssetWriter + * @brief A helper class for writing to MonoPictureAssets + * + * Objects of this class can only be created with MonoPictureAsset::start_write(). + * + * Frames can be written to the MonoPictureAsset by calling write() with a JPEG2000 image + * (a verbatim .j2c file). finalize() must be called after the last frame has been written. + * The action of finalize() can't be done in MonoPictureAssetWriter's destructor as it may + * throw an exception. + */ +class MonoPictureAssetWriter : public PictureAssetWriter +{ +public: + FrameInfo write (uint8_t *, int); + void fake_write (int size); + void finalize (); + +private: + friend class MonoPictureAsset; + + MonoPictureAssetWriter (PictureAsset *, boost::filesystem::path file, Standard standard, bool); + void start (uint8_t *, int); + + /* do this with an opaque pointer so we don't have to include + ASDCP headers + */ + + struct ASDCPState; + boost::shared_ptr _state; +}; + +} + +#endif diff --git a/src/mono_picture_frame.cc b/src/mono_picture_frame.cc index 689a8b21..1237fd90 100644 --- a/src/mono_picture_frame.cc +++ b/src/mono_picture_frame.cc @@ -56,16 +56,16 @@ MonoPictureFrame::MonoPictureFrame (boost::filesystem::path path) } /** Make a picture frame from a 2D (monoscopic) asset. - * @param mxf_path Path to the asset's MXF file. + * @param path Path to the asset's MXF file. * @param n Frame within the asset, not taking EntryPoint into account. * @param c Context for decryption, or 0. */ -MonoPictureFrame::MonoPictureFrame (boost::filesystem::path mxf_path, int n, ASDCP::AESDecContext* c) +MonoPictureFrame::MonoPictureFrame (boost::filesystem::path path, int n, ASDCP::AESDecContext* c) { ASDCP::JP2K::MXFReader reader; - Kumu::Result_t r = reader.OpenRead (mxf_path.string().c_str()); + Kumu::Result_t r = reader.OpenRead (path.string().c_str()); if (ASDCP_FAILURE (r)) { - boost::throw_exception (FileError ("could not open MXF file for reading", mxf_path, r)); + boost::throw_exception (FileError ("could not open MXF file for reading", path, r)); } /* XXX: unfortunate guesswork on this buffer size */ diff --git a/src/mono_picture_frame.h b/src/mono_picture_frame.h index 91089262..d4853d52 100644 --- a/src/mono_picture_frame.h +++ b/src/mono_picture_frame.h @@ -46,7 +46,7 @@ class XYZImage; class MonoPictureFrame : public boost::noncopyable { public: - MonoPictureFrame (boost::filesystem::path mxf_path, int n, ASDCP::AESDecContext *); + MonoPictureFrame (boost::filesystem::path path, int n, ASDCP::AESDecContext *); MonoPictureFrame (boost::filesystem::path path); MonoPictureFrame (); ~MonoPictureFrame (); diff --git a/src/mono_picture_mxf.cc b/src/mono_picture_mxf.cc deleted file mode 100644 index faae8cd8..00000000 --- a/src/mono_picture_mxf.cc +++ /dev/null @@ -1,138 +0,0 @@ -/* - Copyright (C) 2012-2014 Carl Hetherington - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -*/ - -#include "mono_picture_mxf.h" -#include "mono_picture_mxf_writer.h" -#include "AS_DCP.h" -#include "KM_fileio.h" -#include "exceptions.h" -#include "dcp_assert.h" -#include "mono_picture_frame.h" -#include "compose.hpp" - -using std::string; -using std::vector; -using boost::shared_ptr; -using boost::dynamic_pointer_cast; -using namespace dcp; - -MonoPictureMXF::MonoPictureMXF (boost::filesystem::path file) - : PictureMXF (file) -{ - ASDCP::JP2K::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)); - } - - ASDCP::JP2K::PictureDescriptor desc; - if (ASDCP_FAILURE (reader.FillPictureDescriptor (desc))) { - boost::throw_exception (DCPReadError ("could not read video MXF information")); - } - - read_picture_descriptor (desc); - - ASDCP::WriterInfo info; - if (ASDCP_FAILURE (reader.FillWriterInfo (info))) { - boost::throw_exception (DCPReadError ("could not read video MXF information")); - } - - _id = read_writer_info (info); -} - -MonoPictureMXF::MonoPictureMXF (Fraction edit_rate) - : PictureMXF (edit_rate) -{ - -} - -shared_ptr -MonoPictureMXF::get_frame (int n) const -{ - return shared_ptr (new MonoPictureFrame (_file, n, _decryption_context)); -} - -bool -MonoPictureMXF::equals (shared_ptr other, EqualityOptions opt, NoteHandler note) const -{ - if (!dynamic_pointer_cast (other)) { - return false; - } - - ASDCP::JP2K::MXFReader reader_A; - 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)); - } - - ASDCP::JP2K::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)); - } - - ASDCP::JP2K::PictureDescriptor desc_A; - if (ASDCP_FAILURE (reader_A.FillPictureDescriptor (desc_A))) { - boost::throw_exception (DCPReadError ("could not read video MXF information")); - } - ASDCP::JP2K::PictureDescriptor desc_B; - if (ASDCP_FAILURE (reader_B.FillPictureDescriptor (desc_B))) { - boost::throw_exception (DCPReadError ("could not read video MXF information")); - } - - if (!descriptor_equals (desc_A, desc_B, note)) { - return false; - } - - shared_ptr other_picture = dynamic_pointer_cast (other); - DCP_ASSERT (other_picture); - - for (int i = 0; i < _intrinsic_duration; ++i) { - if (i >= other_picture->intrinsic_duration()) { - return false; - } - - note (DCP_PROGRESS, String::compose ("Comparing video frame %1 of %2", i, _intrinsic_duration)); - shared_ptr frame_A = get_frame (i); - shared_ptr frame_B = other_picture->get_frame (i); - - if (!frame_buffer_equals ( - i, opt, note, - frame_A->j2k_data(), frame_A->j2k_size(), - frame_B->j2k_data(), frame_B->j2k_size() - )) { - return false; - } - } - - return true; -} - -shared_ptr -MonoPictureMXF::start_write (boost::filesystem::path file, Standard standard, bool overwrite) -{ - /* XXX: can't we use shared_ptr here? */ - return shared_ptr (new MonoPictureMXFWriter (this, file, standard, overwrite)); -} - -string -MonoPictureMXF::cpl_node_name () const -{ - return "MainPicture"; -} diff --git a/src/mono_picture_mxf.h b/src/mono_picture_mxf.h deleted file mode 100644 index 4e5211ca..00000000 --- a/src/mono_picture_mxf.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - Copyright (C) 2012-2014 Carl Hetherington - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -*/ - -#ifndef LIBDCP_MONO_PICTURE_MXF_H -#define LIBDCP_MONO_PICTURE_MXF_H - -#include "picture_mxf.h" - -namespace dcp { - -class MonoPictureMXFWriter; - -/** @class MonoPictureMXF - * @brief A 2D (monoscopic) picture MXF. - */ -class MonoPictureMXF : public PictureMXF -{ -public: - /** Create a MonoPictureMXF by reading a file. - * @param file MXF file to read. - */ - MonoPictureMXF (boost::filesystem::path file); - - /** Create a MonoPictureMXF with a given edit rate. - * @param edit_rate Edit rate (i.e. frame rate) in frames per second. - */ - MonoPictureMXF (Fraction edit_rate); - - /** Start a progressive write to a MonoPictureMXF */ - boost::shared_ptr start_write (boost::filesystem::path, Standard standard, bool); - - bool equals ( - boost::shared_ptr other, - EqualityOptions opt, - NoteHandler note - ) const; - - boost::shared_ptr get_frame (int n) const; - -private: - std::string cpl_node_name () const; -}; - -} - -#endif diff --git a/src/mono_picture_mxf_writer.cc b/src/mono_picture_mxf_writer.cc deleted file mode 100644 index f0914cdc..00000000 --- a/src/mono_picture_mxf_writer.cc +++ /dev/null @@ -1,111 +0,0 @@ -/* - Copyright (C) 2012-2014 Carl Hetherington - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -*/ - -/** @file src/mono_picture_mxf_writer.cc - * @brief MonoPictureMXFWriter class - */ - -#include "AS_DCP.h" -#include "KM_fileio.h" -#include "mono_picture_mxf_writer.h" -#include "exceptions.h" -#include "picture_mxf.h" -#include "dcp_assert.h" - -#include "picture_mxf_writer_common.cc" - -using std::istream; -using std::ostream; -using std::string; -using boost::shared_ptr; -using namespace dcp; - -struct MonoPictureMXFWriter::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. - */ -MonoPictureMXFWriter::MonoPictureMXFWriter (PictureMXF* asset, boost::filesystem::path file, Standard standard, bool overwrite) - : PictureMXFWriter (asset, file, standard, overwrite) - , _state (new MonoPictureMXFWriter::ASDCPState) -{ - -} - -void -MonoPictureMXFWriter::start (uint8_t* data, int size) -{ - dcp::start (this, _state, _standard, _picture_mxf, data, size); - _picture_mxf->set_frame_rate (_picture_mxf->edit_rate()); -} - -FrameInfo -MonoPictureMXFWriter::write (uint8_t* data, int size) -{ - DCP_ASSERT (!_finalized); - - if (!_started) { - start (data, size); - } - - 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, _encryption_context, 0, &hash); - if (ASDCP_FAILURE (r)) { - boost::throw_exception (MXFFileError ("error in writing video MXF", _file.string(), r)); - } - - ++_frames_written; - return FrameInfo (before_offset, _state->mxf_writer.Tell() - before_offset, hash); -} - -void -MonoPictureMXFWriter::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)); - } - - ++_frames_written; -} - -void -MonoPictureMXFWriter::finalize () -{ - Kumu::Result_t r = _state->mxf_writer.Finalize(); - if (ASDCP_FAILURE (r)) { - boost::throw_exception (MXFFileError ("error in finalizing video MXF", _file.string(), r)); - } - - _picture_mxf->_intrinsic_duration = _frames_written; - PictureMXFWriter::finalize (); -} - diff --git a/src/mono_picture_mxf_writer.h b/src/mono_picture_mxf_writer.h deleted file mode 100644 index 7cad54e0..00000000 --- a/src/mono_picture_mxf_writer.h +++ /dev/null @@ -1,69 +0,0 @@ -/* - Copyright (C) 2012-2014 Carl Hetherington - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -*/ - -/** @file src/mono_picture_mxf_writer.h - * @brief MonoPictureMXFWriter class - */ - -#ifndef LIBDCP_MONO_PICTURE_MXF_WRITER_H -#define LIBDCP_MONO_PICTURE_MXF_WRITER_H - -#include "picture_mxf_writer.h" -#include -#include -#include -#include -#include - -namespace dcp { - -/** @class MonoPictureMXFWriter - * @brief A helper class for writing to MonoPictureMXFs - * - * Objects of this class can only be created with MonoPictureMXF::start_write(). - * - * Frames can be written to the MonoPictureMXF by calling write() with a JPEG2000 image - * (a verbatim .j2c file). finalize() must be called after the last frame has been written. - * The action of finalize() can't be done in MonoPictureAssetWriter's destructor as it may - * throw an exception. - */ -class MonoPictureMXFWriter : public PictureMXFWriter -{ -public: - FrameInfo write (uint8_t *, int); - void fake_write (int size); - void finalize (); - -private: - friend class MonoPictureMXF; - - MonoPictureMXFWriter (PictureMXF *, boost::filesystem::path file, Standard standard, bool); - void start (uint8_t *, int); - - /* do this with an opaque pointer so we don't have to include - ASDCP headers - */ - - struct ASDCPState; - boost::shared_ptr _state; -}; - -} - -#endif diff --git a/src/mxf.h b/src/mxf.h index e05ddbcd..a9f1bfa3 100644 --- a/src/mxf.h +++ b/src/mxf.h @@ -39,7 +39,7 @@ namespace dcp { class MXFMetadata; -class PictureMXFWriter; +class PictureAssetWriter; /** @class MXF * @brief Parent class for classes which represent MXF files. @@ -88,7 +88,7 @@ public: protected: template - friend void start (PictureMXFWriter* writer, boost::shared_ptr

state, Standard standard, Q* mxf, uint8_t* data, int size); + friend void start (PictureAssetWriter* writer, boost::shared_ptr

state, Standard standard, Q* mxf, uint8_t* data, int size); std::string read_writer_info (ASDCP::WriterInfo const &); /** Fill in a ADSCP::WriteInfo struct. diff --git a/src/mxf_writer.cc b/src/mxf_writer.cc deleted file mode 100644 index ab1eac1a..00000000 --- a/src/mxf_writer.cc +++ /dev/null @@ -1,68 +0,0 @@ -/* - Copyright (C) 2012-2014 Carl Hetherington - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -*/ - -/** @file src/mxf_writer.h - * @brief MXFWriter class. - */ - -#include "mxf_writer.h" -#include "mxf.h" -#include "dcp_assert.h" -#include "AS_DCP.h" -#include "KM_prng.h" - -using namespace dcp; - -/** Create an MXFWriter. - * @param mxf MXF that we are writing. - * @param file File to write to. - */ -MXFWriter::MXFWriter (MXF* mxf, boost::filesystem::path file) - : _mxf (mxf) - , _file (file) - , _frames_written (0) - , _finalized (false) - , _encryption_context (0) -{ - if (mxf->key ()) { - _encryption_context = new ASDCP::AESEncContext; - if (ASDCP_FAILURE (_encryption_context->InitKey (mxf->key()->value ()))) { - throw MiscError ("could not set up encryption context"); - } - - uint8_t cbc_buffer[ASDCP::CBC_BLOCK_SIZE]; - - Kumu::FortunaRNG rng; - if (ASDCP_FAILURE (_encryption_context->SetIVec (rng.FillRandom (cbc_buffer, ASDCP::CBC_BLOCK_SIZE)))) { - throw MiscError ("could not set up CBC initialization vector"); - } - } -} - -MXFWriter::~MXFWriter () -{ - delete _encryption_context; -} - -void -MXFWriter::finalize () -{ - DCP_ASSERT (!_finalized); - _finalized = true; -} diff --git a/src/mxf_writer.h b/src/mxf_writer.h deleted file mode 100644 index c7924c9a..00000000 --- a/src/mxf_writer.h +++ /dev/null @@ -1,67 +0,0 @@ -/* - Copyright (C) 2012-2014 Carl Hetherington - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -*/ - -/** @file src/mxf_writer.h - * @brief MXFWriter class. - */ - -#ifndef LIBDCP_MXF_WRITER_H -#define LIBDCP_MXF_WRITER_H - -#include - -namespace ASDCP { - class AESEncContext; -} - -namespace dcp { - -class MXF; - -/** @class MXFWriter - * @brief Parent class for classes which can write MXF files. - * - * The MXFWriter lasts for the duration of the write and is then discarded. - * They can only be created by calling start_write() on an MXF object. - */ -class MXFWriter : public boost::noncopyable -{ -public: - virtual ~MXFWriter (); - virtual void finalize (); - -protected: - MXFWriter (MXF* mxf, boost::filesystem::path file); - - /** MXF that we are writing */ - MXF* _mxf; - /** File that we are writing to */ - boost::filesystem::path _file; - /** Number of `frames' written so far; the definition of a frame - * varies depending on the subclass. - */ - int64_t _frames_written; - /** true if finalize() has been called on this object */ - bool _finalized; - ASDCP::AESEncContext* _encryption_context; -}; - -} - -#endif diff --git a/src/picture_asset.cc b/src/picture_asset.cc new file mode 100644 index 00000000..ef3ff1f4 --- /dev/null +++ b/src/picture_asset.cc @@ -0,0 +1,202 @@ +/* + Copyright (C) 2012-2015 Carl Hetherington + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#include "picture_asset.h" +#include "util.h" +#include "exceptions.h" +#include "xyz_image.h" +#include "picture_asset_writer.h" +#include "dcp_assert.h" +#include "compose.hpp" +#include "AS_DCP.h" +#include "KM_fileio.h" +#include +#include +#include +#include +#include +#include +#include + +using std::string; +using std::ostream; +using std::list; +using std::vector; +using std::max; +using std::stringstream; +using std::pair; +using std::make_pair; +using std::istream; +using std::cout; +using boost::shared_ptr; +using namespace dcp; + +PictureAsset::PictureAsset (boost::filesystem::path file) + : Asset (file) + , _intrinsic_duration (0) +{ + +} + +PictureAsset::PictureAsset (Fraction edit_rate) + : _edit_rate (edit_rate) + , _intrinsic_duration (0) +{ + +} + +void +PictureAsset::read_picture_descriptor (ASDCP::JP2K::PictureDescriptor const & desc) +{ + _size.width = desc.StoredWidth; + _size.height = desc.StoredHeight; + _edit_rate = Fraction (desc.EditRate.Numerator, desc.EditRate.Denominator); + _intrinsic_duration = desc.ContainerDuration; + _frame_rate = Fraction (desc.SampleRate.Numerator, desc.SampleRate.Denominator); + _screen_aspect_ratio = Fraction (desc.AspectRatio.Numerator, desc.AspectRatio.Denominator); +} + +bool +PictureAsset::descriptor_equals ( + ASDCP::JP2K::PictureDescriptor const & a, ASDCP::JP2K::PictureDescriptor const & b, NoteHandler note + ) const +{ + if ( + a.EditRate != b.EditRate || + a.SampleRate != b.SampleRate || + a.StoredWidth != b.StoredWidth || + a.StoredHeight != b.StoredHeight || + a.AspectRatio != b.AspectRatio || + a.Rsize != b.Rsize || + a.Xsize != b.Xsize || + a.Ysize != b.Ysize || + a.XOsize != b.XOsize || + a.YOsize != b.YOsize || + a.XTsize != b.XTsize || + a.YTsize != b.YTsize || + a.XTOsize != b.XTOsize || + a.YTOsize != b.YTOsize || + a.Csize != b.Csize +// a.CodingStyleDefault != b.CodingStyleDefault || +// a.QuantizationDefault != b.QuantizationDefault + ) { + + note (DCP_ERROR, "video MXF picture descriptors differ"); + return false; + } + + if (a.ContainerDuration != b.ContainerDuration) { + note (DCP_ERROR, "video container durations differ"); + } + +// for (unsigned int j = 0; j < ASDCP::JP2K::MaxComponents; ++j) { +// if (a.ImageComponents[j] != b.ImageComponents[j]) { +// notes.pack_start ("video MXF picture descriptors differ"); +// } +// } + + return true; +} + +bool +PictureAsset::frame_buffer_equals ( + int frame, EqualityOptions opt, NoteHandler note, + uint8_t const * data_A, unsigned int size_A, uint8_t const * data_B, unsigned int size_B + ) const +{ + if (size_A == size_B && memcmp (data_A, data_B, size_A) == 0) { + note (DCP_NOTE, "J2K identical"); + /* Easy result; the J2K data is identical */ + return true; + } + + /* Decompress the images to bitmaps */ + shared_ptr image_A = decompress_j2k (const_cast (data_A), size_A, 0); + shared_ptr image_B = decompress_j2k (const_cast (data_B), size_B, 0); + + /* Compare them */ + + vector abs_diffs (image_A->size().width * image_A->size().height * 3); + int d = 0; + int max_diff = 0; + + for (int c = 0; c < 3; ++c) { + + if (image_A->size() != image_B->size()) { + note (DCP_ERROR, String::compose ("image sizes for frame %1 differ", frame)); + return false; + } + + int const pixels = image_A->size().width * image_A->size().height; + for (int j = 0; j < pixels; ++j) { + int const t = abs (image_A->data(c)[j] - image_B->data(c)[j]); + abs_diffs[d++] = t; + max_diff = max (max_diff, t); + } + } + + uint64_t total = 0; + for (vector::iterator j = abs_diffs.begin(); j != abs_diffs.end(); ++j) { + total += *j; + } + + double const mean = double (total) / abs_diffs.size (); + + uint64_t total_squared_deviation = 0; + for (vector::iterator j = abs_diffs.begin(); j != abs_diffs.end(); ++j) { + total_squared_deviation += pow (*j - mean, 2); + } + + double const std_dev = sqrt (double (total_squared_deviation) / abs_diffs.size()); + + note (DCP_NOTE, String::compose ("mean difference %1, deviation %2", mean, std_dev)); + + if (mean > opt.max_mean_pixel_error) { + note ( + DCP_ERROR, + String::compose ("mean %1 out of range %2 in frame %3", mean, opt.max_mean_pixel_error, frame) + ); + + return false; + } + + if (std_dev > opt.max_std_dev_pixel_error) { + note ( + DCP_ERROR, + String::compose ("standard deviation %1 out of range %2 in frame %3", std_dev, opt.max_std_dev_pixel_error, frame) + ); + + return false; + } + + return true; +} + +string +PictureAsset::pkl_type (Standard standard) const +{ + switch (standard) { + case INTEROP: + return "application/x-smpte-mxf;asdcpKind=Picture"; + case SMPTE: + return "application/mxf"; + default: + DCP_ASSERT (false); + } +} diff --git a/src/picture_asset.h b/src/picture_asset.h new file mode 100644 index 00000000..51b69e7c --- /dev/null +++ b/src/picture_asset.h @@ -0,0 +1,126 @@ +/* + Copyright (C) 2012-2014 Carl Hetherington + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#ifndef LIBDCP_PICTURE_ASSET_H +#define LIBDCP_PICTURE_ASSET_H + +/** @file src/picture_asset.h + * @brief PictureAsset class. + */ + +#include "mxf.h" +#include "util.h" +#include "metadata.h" +#include + +namespace ASDCP { + namespace JP2K { + struct PictureDescriptor; + } +} + +namespace dcp +{ + +class MonoPictureFrame; +class StereoPictureFrame; +class PictureAssetWriter; + +/** @class PictureAsset + * @brief An asset made up of JPEG2000 data. + */ +class PictureAsset : public Asset, public MXF +{ +public: + PictureAsset (boost::filesystem::path file); + PictureAsset (Fraction edit_rate); + + virtual boost::shared_ptr start_write ( + boost::filesystem::path file, + Standard standard, + bool overwrite + ) = 0; + + Size size () const { + return _size; + } + + void set_size (Size s) { + _size = s; + } + + Fraction frame_rate () const { + return _frame_rate; + } + + void set_frame_rate (Fraction r) { + _frame_rate = r; + } + + Fraction screen_aspect_ratio () const { + return _screen_aspect_ratio; + } + + void set_screen_aspect_ratio (Fraction r) { + _screen_aspect_ratio = r; + } + + Fraction edit_rate () const { + return _edit_rate; + } + + int64_t intrinsic_duration () const { + return _intrinsic_duration; + } + +protected: + friend class MonoPictureAssetWriter; + friend class StereoPictureAssetWriter; + + bool frame_buffer_equals ( + int frame, EqualityOptions opt, NoteHandler note, + uint8_t const * data_A, unsigned int size_A, uint8_t const * data_B, unsigned int size_B + ) const; + + bool descriptor_equals ( + ASDCP::JP2K::PictureDescriptor const & a, + ASDCP::JP2K::PictureDescriptor const & b, + NoteHandler note + ) const; + + void read_picture_descriptor (ASDCP::JP2K::PictureDescriptor const &); + + Fraction _edit_rate; + /** The total length of this content in video frames. The amount of + * content presented may be less than this. + */ + int64_t _intrinsic_duration; + /** picture size in pixels */ + Size _size; + Fraction _frame_rate; + Fraction _screen_aspect_ratio; + +private: + std::string pkl_type (Standard standard) const; +}; + + +} + +#endif diff --git a/src/picture_asset_writer.cc b/src/picture_asset_writer.cc new file mode 100644 index 00000000..b47aaabd --- /dev/null +++ b/src/picture_asset_writer.cc @@ -0,0 +1,42 @@ +/* + Copyright (C) 2012-2014 Carl Hetherington + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#include "KM_fileio.h" +#include "picture_asset_writer.h" +#include "exceptions.h" +#include "picture_asset.h" +#include "AS_DCP.h" +#include +#include + +using std::istream; +using std::ostream; +using std::string; +using boost::shared_ptr; +using namespace dcp; + +PictureAssetWriter::PictureAssetWriter (PictureAsset* asset, boost::filesystem::path file, Standard standard, bool overwrite) + : AssetWriter (asset, file) + , _picture_asset (asset) + , _started (false) + , _standard (standard) + , _overwrite (overwrite) +{ + asset->set_file (file); +} diff --git a/src/picture_asset_writer.h b/src/picture_asset_writer.h new file mode 100644 index 00000000..48832e43 --- /dev/null +++ b/src/picture_asset_writer.h @@ -0,0 +1,84 @@ +/* + Copyright (C) 2012-2014 Carl Hetherington + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +/** @file src/picture_asset_writer.h + * @brief PictureAssetWriter and FrameInfo classes. + */ + +#ifndef LIBDCP_PICTURE_ASSET_WRITER_H +#define LIBDCP_PICTURE_ASSET_WRITER_H + +#include "metadata.h" +#include "types.h" +#include "asset_writer.h" +#include +#include +#include +#include +#include + +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 (uint64_t o, uint64_t s, std::string h) + : offset (o) + , size (s) + , hash (h) + {} + + uint64_t offset; + uint64_t size; + std::string hash; +}; + +/** @class PictureAssetWriter + * @brief Parent class for classes which write picture assets. + */ +class PictureAssetWriter : public AssetWriter +{ +public: + virtual FrameInfo write (uint8_t *, int) = 0; + virtual void fake_write (int) = 0; + +protected: + template + friend void start (PictureAssetWriter *, boost::shared_ptr

, Standard, Q *, uint8_t *, int); + + PictureAssetWriter (PictureAsset *, boost::filesystem::path, Standard standard, bool); + + PictureAsset* _picture_asset; + bool _started; + Standard _standard; + bool _overwrite; +}; + +} + +#endif diff --git a/src/picture_asset_writer_common.cc b/src/picture_asset_writer_common.cc new file mode 100644 index 00000000..b463cb4a --- /dev/null +++ b/src/picture_asset_writer_common.cc @@ -0,0 +1,64 @@ +/* + Copyright (C) 2012-2014 Carl Hetherington + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +using boost::shared_ptr; + +struct ASDCPStateBase +{ + ASDCPStateBase () + : frame_buffer (4 * Kumu::Megabyte) + {} + + ASDCP::JP2K::CodestreamParser j2k_parser; + ASDCP::JP2K::FrameBuffer frame_buffer; + ASDCP::WriterInfo writer_info; + ASDCP::JP2K::PictureDescriptor picture_descriptor; +}; + +template +void dcp::start (PictureAssetWriter* writer, shared_ptr

state, Standard standard, Q* mxf, uint8_t* data, int size) +{ + mxf->set_file (writer->_file); + + if (ASDCP_FAILURE (state->j2k_parser.OpenReadFrame (data, size, state->frame_buffer))) { + boost::throw_exception (MiscError ("could not parse J2K frame")); + } + + state->j2k_parser.FillPictureDescriptor (state->picture_descriptor); + state->picture_descriptor.EditRate = ASDCP::Rational (mxf->edit_rate().numerator, mxf->edit_rate().denominator); + + mxf->set_size (Size (state->picture_descriptor.StoredWidth, state->picture_descriptor.StoredHeight)); + mxf->set_screen_aspect_ratio (Fraction (state->picture_descriptor.AspectRatio.Numerator, state->picture_descriptor.AspectRatio.Denominator)); + + mxf->fill_writer_info (&state->writer_info, mxf->id(), standard); + + Kumu::Result_t r = state->mxf_writer.OpenWrite ( + mxf->file().string().c_str(), + state->writer_info, + state->picture_descriptor, + 16384, + writer->_overwrite + ); + + if (ASDCP_FAILURE (r)) { + boost::throw_exception (MXFFileError ("could not open MXF file for writing", mxf->file().string(), r)); + } + + writer->_started = true; +} diff --git a/src/picture_mxf.cc b/src/picture_mxf.cc deleted file mode 100644 index caa3d1a6..00000000 --- a/src/picture_mxf.cc +++ /dev/null @@ -1,202 +0,0 @@ -/* - Copyright (C) 2012-2015 Carl Hetherington - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -*/ - -#include "picture_mxf.h" -#include "util.h" -#include "exceptions.h" -#include "xyz_image.h" -#include "picture_mxf_writer.h" -#include "dcp_assert.h" -#include "compose.hpp" -#include "AS_DCP.h" -#include "KM_fileio.h" -#include -#include -#include -#include -#include -#include -#include - -using std::string; -using std::ostream; -using std::list; -using std::vector; -using std::max; -using std::stringstream; -using std::pair; -using std::make_pair; -using std::istream; -using std::cout; -using boost::shared_ptr; -using namespace dcp; - -PictureMXF::PictureMXF (boost::filesystem::path file) - : Asset (file) - , _intrinsic_duration (0) -{ - -} - -PictureMXF::PictureMXF (Fraction edit_rate) - : _edit_rate (edit_rate) - , _intrinsic_duration (0) -{ - -} - -void -PictureMXF::read_picture_descriptor (ASDCP::JP2K::PictureDescriptor const & desc) -{ - _size.width = desc.StoredWidth; - _size.height = desc.StoredHeight; - _edit_rate = Fraction (desc.EditRate.Numerator, desc.EditRate.Denominator); - _intrinsic_duration = desc.ContainerDuration; - _frame_rate = Fraction (desc.SampleRate.Numerator, desc.SampleRate.Denominator); - _screen_aspect_ratio = Fraction (desc.AspectRatio.Numerator, desc.AspectRatio.Denominator); -} - -bool -PictureMXF::descriptor_equals ( - ASDCP::JP2K::PictureDescriptor const & a, ASDCP::JP2K::PictureDescriptor const & b, NoteHandler note - ) const -{ - if ( - a.EditRate != b.EditRate || - a.SampleRate != b.SampleRate || - a.StoredWidth != b.StoredWidth || - a.StoredHeight != b.StoredHeight || - a.AspectRatio != b.AspectRatio || - a.Rsize != b.Rsize || - a.Xsize != b.Xsize || - a.Ysize != b.Ysize || - a.XOsize != b.XOsize || - a.YOsize != b.YOsize || - a.XTsize != b.XTsize || - a.YTsize != b.YTsize || - a.XTOsize != b.XTOsize || - a.YTOsize != b.YTOsize || - a.Csize != b.Csize -// a.CodingStyleDefault != b.CodingStyleDefault || -// a.QuantizationDefault != b.QuantizationDefault - ) { - - note (DCP_ERROR, "video MXF picture descriptors differ"); - return false; - } - - if (a.ContainerDuration != b.ContainerDuration) { - note (DCP_ERROR, "video container durations differ"); - } - -// for (unsigned int j = 0; j < ASDCP::JP2K::MaxComponents; ++j) { -// if (a.ImageComponents[j] != b.ImageComponents[j]) { -// notes.pack_start ("video MXF picture descriptors differ"); -// } -// } - - return true; -} - -bool -PictureMXF::frame_buffer_equals ( - int frame, EqualityOptions opt, NoteHandler note, - uint8_t const * data_A, unsigned int size_A, uint8_t const * data_B, unsigned int size_B - ) const -{ - if (size_A == size_B && memcmp (data_A, data_B, size_A) == 0) { - note (DCP_NOTE, "J2K identical"); - /* Easy result; the J2K data is identical */ - return true; - } - - /* Decompress the images to bitmaps */ - shared_ptr image_A = decompress_j2k (const_cast (data_A), size_A, 0); - shared_ptr image_B = decompress_j2k (const_cast (data_B), size_B, 0); - - /* Compare them */ - - vector abs_diffs (image_A->size().width * image_A->size().height * 3); - int d = 0; - int max_diff = 0; - - for (int c = 0; c < 3; ++c) { - - if (image_A->size() != image_B->size()) { - note (DCP_ERROR, String::compose ("image sizes for frame %1 differ", frame)); - return false; - } - - int const pixels = image_A->size().width * image_A->size().height; - for (int j = 0; j < pixels; ++j) { - int const t = abs (image_A->data(c)[j] - image_B->data(c)[j]); - abs_diffs[d++] = t; - max_diff = max (max_diff, t); - } - } - - uint64_t total = 0; - for (vector::iterator j = abs_diffs.begin(); j != abs_diffs.end(); ++j) { - total += *j; - } - - double const mean = double (total) / abs_diffs.size (); - - uint64_t total_squared_deviation = 0; - for (vector::iterator j = abs_diffs.begin(); j != abs_diffs.end(); ++j) { - total_squared_deviation += pow (*j - mean, 2); - } - - double const std_dev = sqrt (double (total_squared_deviation) / abs_diffs.size()); - - note (DCP_NOTE, String::compose ("mean difference %1, deviation %2", mean, std_dev)); - - if (mean > opt.max_mean_pixel_error) { - note ( - DCP_ERROR, - String::compose ("mean %1 out of range %2 in frame %3", mean, opt.max_mean_pixel_error, frame) - ); - - return false; - } - - if (std_dev > opt.max_std_dev_pixel_error) { - note ( - DCP_ERROR, - String::compose ("standard deviation %1 out of range %2 in frame %3", std_dev, opt.max_std_dev_pixel_error, frame) - ); - - return false; - } - - return true; -} - -string -PictureMXF::pkl_type (Standard standard) const -{ - switch (standard) { - case INTEROP: - return "application/x-smpte-mxf;asdcpKind=Picture"; - case SMPTE: - return "application/mxf"; - default: - DCP_ASSERT (false); - } -} diff --git a/src/picture_mxf.h b/src/picture_mxf.h deleted file mode 100644 index c5066513..00000000 --- a/src/picture_mxf.h +++ /dev/null @@ -1,126 +0,0 @@ -/* - Copyright (C) 2012-2014 Carl Hetherington - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -*/ - -#ifndef LIBDCP_PICTURE_MXF_H -#define LIBDCP_PICTURE_MXF_H - -/** @file src/picture_mxf.h - * @brief PictureMXF class. - */ - -#include "mxf.h" -#include "util.h" -#include "metadata.h" -#include - -namespace ASDCP { - namespace JP2K { - struct PictureDescriptor; - } -} - -namespace dcp -{ - -class MonoPictureFrame; -class StereoPictureFrame; -class PictureMXFWriter; - -/** @class PictureMXF - * @brief An asset made up of JPEG2000 data. - */ -class PictureMXF : public Asset, public MXF -{ -public: - PictureMXF (boost::filesystem::path file); - PictureMXF (Fraction edit_rate); - - virtual boost::shared_ptr start_write ( - boost::filesystem::path file, - Standard standard, - bool overwrite - ) = 0; - - Size size () const { - return _size; - } - - void set_size (Size s) { - _size = s; - } - - Fraction frame_rate () const { - return _frame_rate; - } - - void set_frame_rate (Fraction r) { - _frame_rate = r; - } - - Fraction screen_aspect_ratio () const { - return _screen_aspect_ratio; - } - - void set_screen_aspect_ratio (Fraction r) { - _screen_aspect_ratio = r; - } - - Fraction edit_rate () const { - return _edit_rate; - } - - int64_t intrinsic_duration () const { - return _intrinsic_duration; - } - -protected: - friend class MonoPictureMXFWriter; - friend class StereoPictureMXFWriter; - - bool frame_buffer_equals ( - int frame, EqualityOptions opt, NoteHandler note, - uint8_t const * data_A, unsigned int size_A, uint8_t const * data_B, unsigned int size_B - ) const; - - bool descriptor_equals ( - ASDCP::JP2K::PictureDescriptor const & a, - ASDCP::JP2K::PictureDescriptor const & b, - NoteHandler note - ) const; - - void read_picture_descriptor (ASDCP::JP2K::PictureDescriptor const &); - - Fraction _edit_rate; - /** The total length of this content in video frames. The amount of - * content presented may be less than this. - */ - int64_t _intrinsic_duration; - /** picture size in pixels */ - Size _size; - Fraction _frame_rate; - Fraction _screen_aspect_ratio; - -private: - std::string pkl_type (Standard standard) const; -}; - - -} - -#endif diff --git a/src/picture_mxf_writer.cc b/src/picture_mxf_writer.cc deleted file mode 100644 index 4593c49a..00000000 --- a/src/picture_mxf_writer.cc +++ /dev/null @@ -1,42 +0,0 @@ -/* - Copyright (C) 2012-2014 Carl Hetherington - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -*/ - -#include "KM_fileio.h" -#include "picture_mxf_writer.h" -#include "exceptions.h" -#include "picture_mxf.h" -#include "AS_DCP.h" -#include -#include - -using std::istream; -using std::ostream; -using std::string; -using boost::shared_ptr; -using namespace dcp; - -PictureMXFWriter::PictureMXFWriter (PictureMXF* mxf, boost::filesystem::path file, Standard standard, bool overwrite) - : MXFWriter (mxf, file) - , _picture_mxf (mxf) - , _started (false) - , _standard (standard) - , _overwrite (overwrite) -{ - mxf->set_file (file); -} diff --git a/src/picture_mxf_writer.h b/src/picture_mxf_writer.h deleted file mode 100644 index 6626f8b8..00000000 --- a/src/picture_mxf_writer.h +++ /dev/null @@ -1,84 +0,0 @@ -/* - Copyright (C) 2012-2014 Carl Hetherington - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -*/ - -/** @file src/picture_mxf_writer.h - * @brief PictureMXFWriter and FrameInfo classes. - */ - -#ifndef LIBDCP_PICTURE_MXF_WRITER_H -#define LIBDCP_PICTURE_MXF_WRITER_H - -#include "metadata.h" -#include "types.h" -#include "mxf_writer.h" -#include -#include -#include -#include -#include - -namespace dcp { - -class PictureMXF; - -/** @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 (uint64_t o, uint64_t s, std::string h) - : offset (o) - , size (s) - , hash (h) - {} - - uint64_t offset; - uint64_t size; - std::string hash; -}; - -/** @class PictureMXFWriter - * @brief Parent class for classes which write picture MXF files. - */ -class PictureMXFWriter : public MXFWriter -{ -public: - virtual FrameInfo write (uint8_t *, int) = 0; - virtual void fake_write (int) = 0; - -protected: - template - friend void start (PictureMXFWriter *, boost::shared_ptr

, Standard, Q *, uint8_t *, int); - - PictureMXFWriter (PictureMXF *, boost::filesystem::path, Standard standard, bool); - - PictureMXF* _picture_mxf; - bool _started; - Standard _standard; - bool _overwrite; -}; - -} - -#endif diff --git a/src/picture_mxf_writer_common.cc b/src/picture_mxf_writer_common.cc deleted file mode 100644 index b625d1ff..00000000 --- a/src/picture_mxf_writer_common.cc +++ /dev/null @@ -1,64 +0,0 @@ -/* - Copyright (C) 2012-2014 Carl Hetherington - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -*/ - -using boost::shared_ptr; - -struct ASDCPStateBase -{ - ASDCPStateBase () - : frame_buffer (4 * Kumu::Megabyte) - {} - - ASDCP::JP2K::CodestreamParser j2k_parser; - ASDCP::JP2K::FrameBuffer frame_buffer; - ASDCP::WriterInfo writer_info; - ASDCP::JP2K::PictureDescriptor picture_descriptor; -}; - -template -void dcp::start (PictureMXFWriter* writer, shared_ptr

state, Standard standard, Q* mxf, uint8_t* data, int size) -{ - mxf->set_file (writer->_file); - - if (ASDCP_FAILURE (state->j2k_parser.OpenReadFrame (data, size, state->frame_buffer))) { - boost::throw_exception (MiscError ("could not parse J2K frame")); - } - - state->j2k_parser.FillPictureDescriptor (state->picture_descriptor); - state->picture_descriptor.EditRate = ASDCP::Rational (mxf->edit_rate().numerator, mxf->edit_rate().denominator); - - mxf->set_size (Size (state->picture_descriptor.StoredWidth, state->picture_descriptor.StoredHeight)); - mxf->set_screen_aspect_ratio (Fraction (state->picture_descriptor.AspectRatio.Numerator, state->picture_descriptor.AspectRatio.Denominator)); - - mxf->fill_writer_info (&state->writer_info, mxf->id(), standard); - - Kumu::Result_t r = state->mxf_writer.OpenWrite ( - mxf->file().string().c_str(), - state->writer_info, - state->picture_descriptor, - 16384, - writer->_overwrite - ); - - if (ASDCP_FAILURE (r)) { - boost::throw_exception (MXFFileError ("could not open MXF file for writing", mxf->file().string(), r)); - } - - writer->_started = true; -} diff --git a/src/reel.cc b/src/reel.cc index 3a046297..106fbf40 100644 --- a/src/reel.cc +++ b/src/reel.cc @@ -19,10 +19,10 @@ #include "reel.h" #include "util.h" -#include "picture_mxf.h" -#include "mono_picture_mxf.h" -#include "stereo_picture_mxf.h" -#include "sound_mxf.h" +#include "picture_asset.h" +#include "mono_picture_asset.h" +#include "stereo_picture_asset.h" +#include "sound_asset.h" #include "subtitle_asset.h" #include "reel_mono_picture_asset.h" #include "reel_stereo_picture_asset.h" @@ -140,10 +140,10 @@ Reel::add (DecryptedKDM const & kdm) for (list::iterator i = keys.begin(); i != keys.end(); ++i) { if (i->id() == _main_picture->key_id()) { - _main_picture->mxf()->set_key (i->key ()); + _main_picture->asset()->set_key (i->key ()); } if (i->id() == _main_sound->key_id()) { - _main_sound->mxf()->set_key (i->key ()); + _main_sound->asset()->set_key (i->key ()); } } } @@ -167,14 +167,14 @@ void Reel::resolve_refs (list > objects) { if (_main_picture) { - _main_picture->asset().resolve (objects); + _main_picture->asset_ref().resolve (objects); } if (_main_sound) { - _main_sound->asset().resolve (objects); + _main_sound->asset_ref().resolve (objects); } if (_main_subtitle) { - _main_subtitle->asset().resolve (objects); + _main_subtitle->asset_ref().resolve (objects); } } diff --git a/src/reel_asset.cc b/src/reel_asset.cc index 7f129f90..d56a492b 100644 --- a/src/reel_asset.cc +++ b/src/reel_asset.cc @@ -33,7 +33,7 @@ using namespace dcp; ReelAsset::ReelAsset () : Object (make_uuid ()) - , _asset (_id) + , _asset_ref (_id) , _edit_rate (Fraction (24, 1)) , _intrinsic_duration (0) , _entry_point (0) @@ -50,7 +50,7 @@ ReelAsset::ReelAsset () */ ReelAsset::ReelAsset (shared_ptr asset, Fraction edit_rate, int64_t intrinsic_duration, int64_t entry_point) : Object (asset->id ()) - , _asset (asset) + , _asset_ref (asset) , _edit_rate (edit_rate) , _intrinsic_duration (intrinsic_duration) , _entry_point (entry_point) @@ -63,7 +63,7 @@ ReelAsset::ReelAsset (shared_ptr asset, Fraction edit_rate, int64_t intri ReelAsset::ReelAsset (shared_ptr node) : Object (node->string_child ("Id")) - , _asset (_id) + , _asset_ref (_id) , _annotation_text (node->optional_string_child ("AnnotationText").get_value_or ("")) , _edit_rate (Fraction (node->string_child ("EditRate"))) , _intrinsic_duration (node->number_child ("IntrinsicDuration")) @@ -73,7 +73,7 @@ ReelAsset::ReelAsset (shared_ptr node) { if (_id.length() > 9) { _id = _id.substr (9); - _asset.set_id (_id); + _asset_ref.set_id (_id); } } @@ -91,7 +91,7 @@ ReelAsset::write_to_cpl (xmlpp::Node* node, Standard standard) const a->add_child("IntrinsicDuration")->add_child_text (raw_convert (_intrinsic_duration)); a->add_child("EntryPoint")->add_child_text (raw_convert (_entry_point)); a->add_child("Duration")->add_child_text (raw_convert (_duration)); - a->add_child("Hash")->add_child_text (_asset.object()->hash ()); + a->add_child("Hash")->add_child_text (_asset_ref.object()->hash ()); } pair @@ -143,8 +143,8 @@ ReelAsset::equals (shared_ptr other, EqualityOptions opt, NoteH } } - if (_asset.resolved () && other->_asset.resolved ()) { - return _asset->equals (other->_asset.object (), opt, note); + if (_asset_ref.resolved () && other->_asset_ref.resolved ()) { + return _asset_ref->equals (other->_asset_ref.object (), opt, note); } return true; diff --git a/src/reel_asset.h b/src/reel_asset.h index 7588c063..118f10a1 100644 --- a/src/reel_asset.h +++ b/src/reel_asset.h @@ -55,8 +55,8 @@ public: virtual bool equals (boost::shared_ptr, EqualityOptions, NoteHandler) const; /** @return a Ref to our actual asset */ - Ref& asset () { - return _asset; + Ref& asset_ref () { + return _asset_ref; } int64_t entry_point () const { @@ -81,7 +81,7 @@ protected: /** Reference to the asset (MXF or XML file) that this reel entry * applies to. */ - Ref _asset; + Ref _asset_ref; private: diff --git a/src/reel_mono_picture_asset.cc b/src/reel_mono_picture_asset.cc index b4ed6301..d41cc2ac 100644 --- a/src/reel_mono_picture_asset.cc +++ b/src/reel_mono_picture_asset.cc @@ -1,5 +1,5 @@ /* - Copyright (C) 2014 Carl Hetherington + Copyright (C) 2014-2015 Carl Hetherington This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -22,7 +22,7 @@ */ #include "reel_mono_picture_asset.h" -#include "mono_picture_mxf.h" +#include "mono_picture_asset.h" #include using std::string; @@ -34,8 +34,8 @@ ReelMonoPictureAsset::ReelMonoPictureAsset () } -ReelMonoPictureAsset::ReelMonoPictureAsset (boost::shared_ptr mxf, int64_t entry_point) - : ReelPictureAsset (mxf, entry_point) +ReelMonoPictureAsset::ReelMonoPictureAsset (boost::shared_ptr asset, int64_t entry_point) + : ReelPictureAsset (asset, entry_point) { } diff --git a/src/reel_mono_picture_asset.h b/src/reel_mono_picture_asset.h index a25550a4..5fcb31c8 100644 --- a/src/reel_mono_picture_asset.h +++ b/src/reel_mono_picture_asset.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2014 Carl Hetherington + Copyright (C) 2014-2015 Carl Hetherington This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -28,16 +28,16 @@ namespace dcp { -class MonoPictureMXF; +class MonoPictureAsset; /** @class ReelMonoPictureAsset - * @brief Part of a Reel's description which refers to a monoscopic picture MXF. + * @brief Part of a Reel's description which refers to a monoscopic picture asset. */ class ReelMonoPictureAsset : public ReelPictureAsset { public: ReelMonoPictureAsset (); - ReelMonoPictureAsset (boost::shared_ptr content, int64_t entry_point); + ReelMonoPictureAsset (boost::shared_ptr asset, int64_t entry_point); ReelMonoPictureAsset (boost::shared_ptr); private: diff --git a/src/reel_mxf_asset.h b/src/reel_mxf_asset.h index c9637549..2dc3af73 100644 --- a/src/reel_mxf_asset.h +++ b/src/reel_mxf_asset.h @@ -37,7 +37,7 @@ class ReelMXFAsset : public ReelAsset { public: ReelMXFAsset (); - ReelMXFAsset (boost::shared_ptr mxf, boost::optional key_id, Fraction edit_rate, int64_t intrinsic_duration, int64_t entry_point); + ReelMXFAsset (boost::shared_ptr asset, boost::optional key_id, Fraction edit_rate, int64_t intrinsic_duration, int64_t entry_point); ReelMXFAsset (boost::shared_ptr); /** @return the 4-character key type for this MXF (MDIK, MDAK, etc.) */ diff --git a/src/reel_picture_asset.cc b/src/reel_picture_asset.cc index d222095c..fd18dc30 100644 --- a/src/reel_picture_asset.cc +++ b/src/reel_picture_asset.cc @@ -22,7 +22,7 @@ */ #include "reel_picture_asset.h" -#include "picture_mxf.h" +#include "picture_asset.h" #include "dcp_assert.h" #include "compose.hpp" #include @@ -43,7 +43,7 @@ ReelPictureAsset::ReelPictureAsset () } -ReelPictureAsset::ReelPictureAsset (shared_ptr asset, int64_t entry_point) +ReelPictureAsset::ReelPictureAsset (shared_ptr asset, int64_t entry_point) : ReelMXFAsset (asset, asset->key_id(), asset->edit_rate(), asset->intrinsic_duration(), entry_point) , _frame_rate (asset->frame_rate ()) , _screen_aspect_ratio (asset->screen_aspect_ratio ()) diff --git a/src/reel_picture_asset.h b/src/reel_picture_asset.h index fd4d11fc..a41cd9d2 100644 --- a/src/reel_picture_asset.h +++ b/src/reel_picture_asset.h @@ -25,26 +25,26 @@ #define LIBDCP_REEL_PICTURE_ASSET_H #include "reel_mxf_asset.h" -#include "picture_mxf.h" +#include "picture_asset.h" namespace dcp { /** @class ReelPictureAsset - * @brief Part of a Reel's description which refers to a picture MXF. + * @brief Part of a Reel's description which refers to a picture asset. */ class ReelPictureAsset : public ReelMXFAsset { public: ReelPictureAsset (); - ReelPictureAsset (boost::shared_ptr asset, int64_t entry_point); + ReelPictureAsset (boost::shared_ptr asset, int64_t entry_point); ReelPictureAsset (boost::shared_ptr); virtual void write_to_cpl (xmlpp::Node* node, Standard standard) const; virtual bool equals (boost::shared_ptr, EqualityOptions, NoteHandler) const; - /** @return the PictureMXF that this object refers to */ - boost::shared_ptr mxf () { - return boost::dynamic_pointer_cast (_asset.object ()); + /** @return the PictureAsset that this object refers to */ + boost::shared_ptr asset () { + return boost::dynamic_pointer_cast (_asset_ref.object ()); } /** @return picture frame rate */ diff --git a/src/reel_sound_asset.cc b/src/reel_sound_asset.cc index 504d376d..b3ca5234 100644 --- a/src/reel_sound_asset.cc +++ b/src/reel_sound_asset.cc @@ -29,7 +29,7 @@ using std::string; using boost::shared_ptr; using namespace dcp; -ReelSoundAsset::ReelSoundAsset (shared_ptr asset, int64_t entry_point) +ReelSoundAsset::ReelSoundAsset (shared_ptr asset, int64_t entry_point) : ReelMXFAsset (asset, asset->key_id(), asset->edit_rate(), asset->intrinsic_duration(), entry_point) { diff --git a/src/reel_sound_asset.h b/src/reel_sound_asset.h index 92667429..d7eee59d 100644 --- a/src/reel_sound_asset.h +++ b/src/reel_sound_asset.h @@ -22,7 +22,7 @@ */ #include "reel_mxf_asset.h" -#include "sound_mxf.h" +#include "sound_asset.h" #include #include @@ -34,19 +34,19 @@ namespace dcp { class ReelSoundAsset : public ReelMXFAsset { public: - ReelSoundAsset (boost::shared_ptr content, int64_t entry_point); + ReelSoundAsset (boost::shared_ptr content, int64_t entry_point); ReelSoundAsset (boost::shared_ptr); void write_to_cpl (xmlpp::Node* node, Standard standard) const; - /** @return the SoundMXF that this object refers to */ - boost::shared_ptr mxf () { - return boost::dynamic_pointer_cast (_asset.object ()); + /** @return the SoundAsset that this object refers to */ + boost::shared_ptr asset () { + return boost::dynamic_pointer_cast (_asset_ref.object ()); } - /** @return the SoundMXF that this object refers to */ - boost::shared_ptr mxf () const { - return boost::dynamic_pointer_cast (_asset.object ()); + /** @return the SoundAsset that this object refers to */ + boost::shared_ptr asset () const { + return boost::dynamic_pointer_cast (_asset_ref.object ()); } private: diff --git a/src/reel_stereo_picture_asset.cc b/src/reel_stereo_picture_asset.cc index 09178dc2..e6e17f63 100644 --- a/src/reel_stereo_picture_asset.cc +++ b/src/reel_stereo_picture_asset.cc @@ -22,7 +22,7 @@ */ #include "reel_stereo_picture_asset.h" -#include "stereo_picture_mxf.h" +#include "stereo_picture_asset.h" #include using std::string; @@ -36,7 +36,7 @@ ReelStereoPictureAsset::ReelStereoPictureAsset () } -ReelStereoPictureAsset::ReelStereoPictureAsset (boost::shared_ptr mxf, int64_t entry_point) +ReelStereoPictureAsset::ReelStereoPictureAsset (boost::shared_ptr mxf, int64_t entry_point) : ReelPictureAsset (mxf, entry_point) { diff --git a/src/reel_stereo_picture_asset.h b/src/reel_stereo_picture_asset.h index 57cc4da1..df939a9c 100644 --- a/src/reel_stereo_picture_asset.h +++ b/src/reel_stereo_picture_asset.h @@ -28,7 +28,7 @@ namespace dcp { -class StereoPictureMXF; +class StereoPictureAsset; /** @class ReelStereoPictureAsset * @brief Part of a Reel's description which refers to a stereoscopic picture MXF. @@ -37,7 +37,7 @@ class ReelStereoPictureAsset : public ReelPictureAsset { public: ReelStereoPictureAsset (); - ReelStereoPictureAsset (boost::shared_ptr content, int64_t entry_point); + ReelStereoPictureAsset (boost::shared_ptr content, int64_t entry_point); ReelStereoPictureAsset (boost::shared_ptr); private: diff --git a/src/reel_subtitle_asset.h b/src/reel_subtitle_asset.h index f296fdc6..55881f7e 100644 --- a/src/reel_subtitle_asset.h +++ b/src/reel_subtitle_asset.h @@ -41,7 +41,7 @@ public: ReelSubtitleAsset (boost::shared_ptr); boost::shared_ptr subtitle_asset () const { - return boost::dynamic_pointer_cast (_asset.object ()); + return boost::dynamic_pointer_cast (_asset_ref.object ()); } private: diff --git a/src/sound_asset.cc b/src/sound_asset.cc new file mode 100644 index 00000000..3d23b426 --- /dev/null +++ b/src/sound_asset.cc @@ -0,0 +1,180 @@ +/* + Copyright (C) 2012-2014 Carl Hetherington + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +/** @file src/sound_mxf.cc + * @brief SoundAsset class. + */ + +#include "sound_asset.h" +#include "util.h" +#include "exceptions.h" +#include "sound_frame.h" +#include "sound_asset_writer.h" +#include "compose.hpp" +#include "KM_fileio.h" +#include "AS_DCP.h" +#include "dcp_assert.h" +#include +#include +#include +#include + +using std::string; +using std::stringstream; +using std::ostream; +using std::vector; +using std::list; +using boost::shared_ptr; +using namespace dcp; + +SoundAsset::SoundAsset (boost::filesystem::path file) + : Asset (file) +{ + 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)); + } + + ASDCP::PCM::AudioDescriptor desc; + if (ASDCP_FAILURE (reader.FillAudioDescriptor (desc))) { + boost::throw_exception (DCPReadError ("could not read audio MXF information")); + } + + _sampling_rate = desc.AudioSamplingRate.Numerator / desc.AudioSamplingRate.Denominator; + _channels = desc.ChannelCount; + _edit_rate = Fraction (desc.EditRate.Numerator, desc.EditRate.Denominator); + + _intrinsic_duration = desc.ContainerDuration; + + ASDCP::WriterInfo info; + if (ASDCP_FAILURE (reader.FillWriterInfo (info))) { + boost::throw_exception (DCPReadError ("could not read audio MXF information")); + } + + _id = read_writer_info (info); +} + +SoundAsset::SoundAsset (Fraction edit_rate, int sampling_rate, int channels) + : _edit_rate (edit_rate) + , _intrinsic_duration (0) + , _channels (channels) + , _sampling_rate (sampling_rate) +{ + +} + +bool +SoundAsset::equals (shared_ptr other, EqualityOptions opt, NoteHandler note) const +{ + ASDCP::PCM::MXFReader reader_A; + 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)); + } + + 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", file().string(), r)); + } + + ASDCP::PCM::AudioDescriptor desc_A; + if (ASDCP_FAILURE (reader_A.FillAudioDescriptor (desc_A))) { + boost::throw_exception (DCPReadError ("could not read audio MXF information")); + } + ASDCP::PCM::AudioDescriptor desc_B; + if (ASDCP_FAILURE (reader_B.FillAudioDescriptor (desc_B))) { + boost::throw_exception (DCPReadError ("could not read audio MXF information")); + } + + if ( + desc_A.EditRate != desc_B.EditRate || + desc_A.AudioSamplingRate != desc_B.AudioSamplingRate || + desc_A.Locked != desc_B.Locked || + desc_A.ChannelCount != desc_B.ChannelCount || + desc_A.QuantizationBits != desc_B.QuantizationBits || + desc_A.BlockAlign != desc_B.BlockAlign || + desc_A.AvgBps != desc_B.AvgBps || + desc_A.LinkedTrackID != desc_B.LinkedTrackID || + desc_A.ContainerDuration != desc_B.ContainerDuration +// desc_A.ChannelFormat != desc_B.ChannelFormat || + ) { + + note (DCP_ERROR, "audio MXF picture descriptors differ"); + return false; + } + + ASDCP::PCM::FrameBuffer buffer_A (1 * Kumu::Megabyte); + ASDCP::PCM::FrameBuffer buffer_B (1 * Kumu::Megabyte); + + for (int i = 0; i < _intrinsic_duration; ++i) { + if (ASDCP_FAILURE (reader_A.ReadFrame (i, buffer_A))) { + boost::throw_exception (DCPReadError ("could not read audio frame")); + } + + if (ASDCP_FAILURE (reader_B.ReadFrame (i, buffer_B))) { + boost::throw_exception (DCPReadError ("could not read audio frame")); + } + + if (buffer_A.Size() != buffer_B.Size()) { + note (DCP_ERROR, String::compose ("sizes of audio data for frame %1 differ", i)); + return false; + } + + if (memcmp (buffer_A.RoData(), buffer_B.RoData(), buffer_A.Size()) != 0) { + for (uint32_t i = 0; i < buffer_A.Size(); ++i) { + int const d = abs (buffer_A.RoData()[i] - buffer_B.RoData()[i]); + if (d > opt.max_audio_sample_error) { + note (DCP_ERROR, String::compose ("PCM data difference of %1", d)); + return false; + } + } + } + } + + return true; +} + +shared_ptr +SoundAsset::get_frame (int n) const +{ + /* XXX: should add on entry point here? */ + return shared_ptr (new SoundFrame (file(), n, _decryption_context)); +} + +shared_ptr +SoundAsset::start_write (boost::filesystem::path file, Standard standard) +{ + /* XXX: can't we use a shared_ptr here? */ + return shared_ptr (new SoundAssetWriter (this, file, standard)); +} + +string +SoundAsset::pkl_type (Standard standard) const +{ + switch (standard) { + case INTEROP: + return "application/x-smpte-mxf;asdcpKind=Sound"; + case SMPTE: + return "application/mxf"; + default: + DCP_ASSERT (false); + } +} diff --git a/src/sound_asset.h b/src/sound_asset.h new file mode 100644 index 00000000..5a7dc214 --- /dev/null +++ b/src/sound_asset.h @@ -0,0 +1,90 @@ +/* + Copyright (C) 2012-2014 Carl Hetherington + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +/** @file src/sound_asset.h + * @brief SoundAsset class + */ + +#ifndef LIBDCP_SOUND_ASSET_H +#define LIBDCP_SOUND_ASSET_H + +#include "mxf.h" +#include "types.h" +#include "metadata.h" + +namespace dcp +{ + +class SoundFrame; +class SoundAssetWriter; + +/** @class SoundAsset + * @brief Representation of a sound asset + */ +class SoundAsset : public Asset, public MXF +{ +public: + SoundAsset (boost::filesystem::path file); + SoundAsset (Fraction edit_rate, int sampling_rate, int channels); + + boost::shared_ptr start_write (boost::filesystem::path file, Standard standard); + + bool equals ( + boost::shared_ptr other, + EqualityOptions opt, + NoteHandler note + ) const; + + boost::shared_ptr get_frame (int n) const; + + /** @return number of channels */ + int channels () const { + return _channels; + } + + /** @return sampling rate in Hz */ + int sampling_rate () const { + return _sampling_rate; + } + + Fraction edit_rate () const { + return _edit_rate; + } + + int64_t intrinsic_duration () const { + return _intrinsic_duration; + } + +private: + friend class SoundAssetWriter; + + std::string pkl_type (Standard standard) const; + + Fraction _edit_rate; + /** 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 +}; + +} + +#endif diff --git a/src/sound_asset_writer.cc b/src/sound_asset_writer.cc new file mode 100644 index 00000000..8d302ed3 --- /dev/null +++ b/src/sound_asset_writer.cc @@ -0,0 +1,121 @@ +/* + Copyright (C) 2012-2014 Carl Hetherington + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#include "sound_asset_writer.h" +#include "sound_asset.h" +#include "exceptions.h" +#include "dcp_assert.h" +#include "compose.hpp" +#include "AS_DCP.h" + +using namespace dcp; + +struct SoundAssetWriter::ASDCPState +{ + ASDCP::PCM::MXFWriter mxf_writer; + ASDCP::PCM::FrameBuffer frame_buffer; + ASDCP::WriterInfo writer_info; + ASDCP::PCM::AudioDescriptor audio_desc; +}; + +SoundAssetWriter::SoundAssetWriter (SoundAsset* asset, boost::filesystem::path file, Standard standard) + : AssetWriter (asset, file) + , _state (new SoundAssetWriter::ASDCPState) + , _sound_asset (asset) + , _frame_buffer_offset (0) +{ + /* Derived from ASDCP::Wav::SimpleWaveHeader::FillADesc */ + _state->audio_desc.EditRate = ASDCP::Rational (_sound_asset->edit_rate().numerator, _sound_asset->edit_rate().denominator); + _state->audio_desc.AudioSamplingRate = ASDCP::Rational (_sound_asset->sampling_rate(), 1); + _state->audio_desc.Locked = 0; + _state->audio_desc.ChannelCount = _sound_asset->channels (); + _state->audio_desc.QuantizationBits = 24; + _state->audio_desc.BlockAlign = 3 * _sound_asset->channels(); + _state->audio_desc.AvgBps = _sound_asset->sampling_rate() * _state->audio_desc.BlockAlign; + _state->audio_desc.LinkedTrackID = 0; + _state->audio_desc.ChannelFormat = ASDCP::PCM::CF_NONE; + + _state->frame_buffer.Capacity (ASDCP::PCM::CalcFrameBufferSize (_state->audio_desc)); + _state->frame_buffer.Size (ASDCP::PCM::CalcFrameBufferSize (_state->audio_desc)); + memset (_state->frame_buffer.Data(), 0, _state->frame_buffer.Capacity()); + + _sound_asset->fill_writer_info (&_state->writer_info, _sound_asset->id(), standard); + + Kumu::Result_t r = _state->mxf_writer.OpenWrite (file.string().c_str(), _state->writer_info, _state->audio_desc); + if (ASDCP_FAILURE (r)) { + boost::throw_exception (FileError ("could not open audio MXF for writing", file.string(), r)); + } + + _sound_asset->set_file (file); +} + +void +SoundAssetWriter::write (float const * const * data, int frames) +{ + DCP_ASSERT (!_finalized); + + for (int i = 0; i < frames; ++i) { + + byte_t* out = _state->frame_buffer.Data() + _frame_buffer_offset; + + /* Write one sample per channel */ + for (int j = 0; j < _sound_asset->channels(); ++j) { + int32_t const s = data[j][i] * (1 << 23); + *out++ = (s & 0xff); + *out++ = (s & 0xff00) >> 8; + *out++ = (s & 0xff0000) >> 16; + } + _frame_buffer_offset += 3 * _sound_asset->channels(); + + 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())) { + write_current_frame (); + _frame_buffer_offset = 0; + memset (_state->frame_buffer.Data(), 0, _state->frame_buffer.Capacity()); + } + } +} + +void +SoundAssetWriter::write_current_frame () +{ + ASDCP::Result_t const r = _state->mxf_writer.WriteFrame (_state->frame_buffer, _encryption_context, 0); + if (ASDCP_FAILURE (r)) { + boost::throw_exception (MiscError (String::compose ("could not write audio MXF frame (%1)", int (r)))); + } + + ++_frames_written; +} + +void +SoundAssetWriter::finalize () +{ + if (_frame_buffer_offset > 0) { + write_current_frame (); + } + + if (ASDCP_FAILURE (_state->mxf_writer.Finalize())) { + boost::throw_exception (MiscError ("could not finalise audio MXF")); + } + + _sound_asset->_intrinsic_duration = _frames_written; + AssetWriter::finalize (); +} diff --git a/src/sound_asset_writer.h b/src/sound_asset_writer.h new file mode 100644 index 00000000..8c54b618 --- /dev/null +++ b/src/sound_asset_writer.h @@ -0,0 +1,68 @@ +/* + Copyright (C) 2012-2014 Carl Hetherington + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +/** @file src/sound_asset_writer.h + * @brief SoundAssetWriter class. + */ + +#include "asset_writer.h" +#include "types.h" +#include +#include + +namespace dcp { + +class SoundFrame; +class SoundAsset; + +/** @class SoundAssetWriter + * @brief A helper class for writing to SoundAssets. + * + * Objects of this class can only be created with SoundAsset::start_write(). + * + * Sound samples can be written to the SoundAsset by calling write() with + * a buffer of float values. finalize() must be called after the last samples + * have been written. + */ +class SoundAssetWriter : public AssetWriter +{ +public: + void write (float const * const *, int); + void finalize (); + +private: + friend class SoundAsset; + + SoundAssetWriter (SoundAsset *, boost::filesystem::path, Standard standard); + + void write_current_frame (); + + /* do this with an opaque pointer so we don't have to include + ASDCP headers + */ + + struct ASDCPState; + boost::shared_ptr _state; + + SoundAsset* _sound_asset; + int _frame_buffer_offset; +}; + +} + diff --git a/src/sound_frame.cc b/src/sound_frame.cc index c79b29b3..166ac584 100644 --- a/src/sound_frame.cc +++ b/src/sound_frame.cc @@ -29,12 +29,12 @@ using namespace std; using namespace dcp; -SoundFrame::SoundFrame (boost::filesystem::path mxf_path, int n, ASDCP::AESDecContext* c) +SoundFrame::SoundFrame (boost::filesystem::path path, int n, ASDCP::AESDecContext* c) { ASDCP::PCM::MXFReader reader; - Kumu::Result_t r = reader.OpenRead (mxf_path.string().c_str()); + Kumu::Result_t r = reader.OpenRead (path.string().c_str()); if (ASDCP_FAILURE (r)) { - boost::throw_exception (FileError ("could not open MXF file for reading", mxf_path, r)); + boost::throw_exception (FileError ("could not open MXF file for reading", path, r)); } /* XXX: unfortunate guesswork on this buffer size */ diff --git a/src/sound_frame.h b/src/sound_frame.h index 26f738d3..8b53dd71 100644 --- a/src/sound_frame.h +++ b/src/sound_frame.h @@ -44,7 +44,7 @@ namespace dcp { class SoundFrame : public boost::noncopyable { public: - SoundFrame (boost::filesystem::path mxf_path, int n, ASDCP::AESDecContext *); + SoundFrame (boost::filesystem::path path, int n, ASDCP::AESDecContext *); ~SoundFrame (); uint8_t const * data () const; diff --git a/src/sound_mxf.cc b/src/sound_mxf.cc deleted file mode 100644 index 19a30bff..00000000 --- a/src/sound_mxf.cc +++ /dev/null @@ -1,183 +0,0 @@ -/* - Copyright (C) 2012-2014 Carl Hetherington - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -*/ - -/** @file src/sound_mxf.cc - * @brief SoundMXF class. - */ - -#include "sound_mxf.h" -#include "util.h" -#include "exceptions.h" -#include "sound_frame.h" -#include "sound_mxf_writer.h" -#include "compose.hpp" -#include "KM_fileio.h" -#include "AS_DCP.h" -#include "dcp_assert.h" -#include -#include -#include -#include - -using std::string; -using std::stringstream; -using std::ostream; -using std::vector; -using std::list; -using boost::shared_ptr; -using namespace dcp; - -SoundMXF::SoundMXF (boost::filesystem::path file) - : Asset (file) - , _intrinsic_duration (0) - , _channels (0) - , _sampling_rate (0) -{ - 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)); - } - - ASDCP::PCM::AudioDescriptor desc; - if (ASDCP_FAILURE (reader.FillAudioDescriptor (desc))) { - boost::throw_exception (DCPReadError ("could not read audio MXF information")); - } - - _sampling_rate = desc.AudioSamplingRate.Numerator / desc.AudioSamplingRate.Denominator; - _channels = desc.ChannelCount; - _edit_rate = Fraction (desc.EditRate.Numerator, desc.EditRate.Denominator); - - _intrinsic_duration = desc.ContainerDuration; - - ASDCP::WriterInfo info; - if (ASDCP_FAILURE (reader.FillWriterInfo (info))) { - boost::throw_exception (DCPReadError ("could not read audio MXF information")); - } - - _id = read_writer_info (info); -} - -SoundMXF::SoundMXF (Fraction edit_rate, int sampling_rate, int channels) - : _edit_rate (edit_rate) - , _intrinsic_duration (0) - , _channels (channels) - , _sampling_rate (sampling_rate) -{ - -} - -bool -SoundMXF::equals (shared_ptr other, EqualityOptions opt, NoteHandler note) const -{ - ASDCP::PCM::MXFReader reader_A; - 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)); - } - - 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", file().string(), r)); - } - - ASDCP::PCM::AudioDescriptor desc_A; - if (ASDCP_FAILURE (reader_A.FillAudioDescriptor (desc_A))) { - boost::throw_exception (DCPReadError ("could not read audio MXF information")); - } - ASDCP::PCM::AudioDescriptor desc_B; - if (ASDCP_FAILURE (reader_B.FillAudioDescriptor (desc_B))) { - boost::throw_exception (DCPReadError ("could not read audio MXF information")); - } - - if ( - desc_A.EditRate != desc_B.EditRate || - desc_A.AudioSamplingRate != desc_B.AudioSamplingRate || - desc_A.Locked != desc_B.Locked || - desc_A.ChannelCount != desc_B.ChannelCount || - desc_A.QuantizationBits != desc_B.QuantizationBits || - desc_A.BlockAlign != desc_B.BlockAlign || - desc_A.AvgBps != desc_B.AvgBps || - desc_A.LinkedTrackID != desc_B.LinkedTrackID || - desc_A.ContainerDuration != desc_B.ContainerDuration -// desc_A.ChannelFormat != desc_B.ChannelFormat || - ) { - - note (DCP_ERROR, "audio MXF picture descriptors differ"); - return false; - } - - ASDCP::PCM::FrameBuffer buffer_A (1 * Kumu::Megabyte); - ASDCP::PCM::FrameBuffer buffer_B (1 * Kumu::Megabyte); - - for (int i = 0; i < _intrinsic_duration; ++i) { - if (ASDCP_FAILURE (reader_A.ReadFrame (i, buffer_A))) { - boost::throw_exception (DCPReadError ("could not read audio frame")); - } - - if (ASDCP_FAILURE (reader_B.ReadFrame (i, buffer_B))) { - boost::throw_exception (DCPReadError ("could not read audio frame")); - } - - if (buffer_A.Size() != buffer_B.Size()) { - note (DCP_ERROR, String::compose ("sizes of audio data for frame %1 differ", i)); - return false; - } - - if (memcmp (buffer_A.RoData(), buffer_B.RoData(), buffer_A.Size()) != 0) { - for (uint32_t i = 0; i < buffer_A.Size(); ++i) { - int const d = abs (buffer_A.RoData()[i] - buffer_B.RoData()[i]); - if (d > opt.max_audio_sample_error) { - note (DCP_ERROR, String::compose ("PCM data difference of %1", d)); - return false; - } - } - } - } - - return true; -} - -shared_ptr -SoundMXF::get_frame (int n) const -{ - /* XXX: should add on entry point here? */ - return shared_ptr (new SoundFrame (file(), n, _decryption_context)); -} - -shared_ptr -SoundMXF::start_write (boost::filesystem::path file, Standard standard) -{ - /* XXX: can't we use a shared_ptr here? */ - return shared_ptr (new SoundMXFWriter (this, file, standard)); -} - -string -SoundMXF::pkl_type (Standard standard) const -{ - switch (standard) { - case INTEROP: - return "application/x-smpte-mxf;asdcpKind=Sound"; - case SMPTE: - return "application/mxf"; - default: - DCP_ASSERT (false); - } -} diff --git a/src/sound_mxf.h b/src/sound_mxf.h deleted file mode 100644 index ed0a60d6..00000000 --- a/src/sound_mxf.h +++ /dev/null @@ -1,90 +0,0 @@ -/* - Copyright (C) 2012-2014 Carl Hetherington - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -*/ - -/** @file src/sound_mxf.h - * @brief SoundMXF class - */ - -#ifndef LIBDCP_SOUND_MXF_H -#define LIBDCP_SOUND_MXF_H - -#include "mxf.h" -#include "types.h" -#include "metadata.h" - -namespace dcp -{ - -class SoundFrame; -class SoundMXFWriter; - -/** @class SoundMXF - * @brief Representation of a MXF file containing sound - */ -class SoundMXF : public Asset, public MXF -{ -public: - SoundMXF (boost::filesystem::path file); - SoundMXF (Fraction edit_rate, int sampling_rate, int channels); - - boost::shared_ptr start_write (boost::filesystem::path file, Standard standard); - - bool equals ( - boost::shared_ptr other, - EqualityOptions opt, - NoteHandler note - ) const; - - boost::shared_ptr get_frame (int n) const; - - /** @return number of channels */ - int channels () const { - return _channels; - } - - /** @return sampling rate in Hz */ - int sampling_rate () const { - return _sampling_rate; - } - - Fraction edit_rate () const { - return _edit_rate; - } - - int64_t intrinsic_duration () const { - return _intrinsic_duration; - } - -private: - friend class SoundMXFWriter; - - std::string pkl_type (Standard standard) const; - - Fraction _edit_rate; - /** 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 -}; - -} - -#endif diff --git a/src/sound_mxf_writer.cc b/src/sound_mxf_writer.cc deleted file mode 100644 index 71b72aa8..00000000 --- a/src/sound_mxf_writer.cc +++ /dev/null @@ -1,121 +0,0 @@ -/* - Copyright (C) 2012-2014 Carl Hetherington - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -*/ - -#include "sound_mxf_writer.h" -#include "sound_mxf.h" -#include "exceptions.h" -#include "dcp_assert.h" -#include "compose.hpp" -#include "AS_DCP.h" - -using namespace dcp; - -struct SoundMXFWriter::ASDCPState -{ - ASDCP::PCM::MXFWriter mxf_writer; - ASDCP::PCM::FrameBuffer frame_buffer; - ASDCP::WriterInfo writer_info; - ASDCP::PCM::AudioDescriptor audio_desc; -}; - -SoundMXFWriter::SoundMXFWriter (SoundMXF* m, boost::filesystem::path file, Standard standard) - : MXFWriter (m, file) - , _state (new SoundMXFWriter::ASDCPState) - , _sound_mxf (m) - , _frame_buffer_offset (0) -{ - /* Derived from ASDCP::Wav::SimpleWaveHeader::FillADesc */ - _state->audio_desc.EditRate = ASDCP::Rational (_sound_mxf->edit_rate().numerator, _sound_mxf->edit_rate().denominator); - _state->audio_desc.AudioSamplingRate = ASDCP::Rational (_sound_mxf->sampling_rate(), 1); - _state->audio_desc.Locked = 0; - _state->audio_desc.ChannelCount = _sound_mxf->channels (); - _state->audio_desc.QuantizationBits = 24; - _state->audio_desc.BlockAlign = 3 * _sound_mxf->channels(); - _state->audio_desc.AvgBps = _sound_mxf->sampling_rate() * _state->audio_desc.BlockAlign; - _state->audio_desc.LinkedTrackID = 0; - _state->audio_desc.ChannelFormat = ASDCP::PCM::CF_NONE; - - _state->frame_buffer.Capacity (ASDCP::PCM::CalcFrameBufferSize (_state->audio_desc)); - _state->frame_buffer.Size (ASDCP::PCM::CalcFrameBufferSize (_state->audio_desc)); - memset (_state->frame_buffer.Data(), 0, _state->frame_buffer.Capacity()); - - _sound_mxf->fill_writer_info (&_state->writer_info, _sound_mxf->id(), standard); - - Kumu::Result_t r = _state->mxf_writer.OpenWrite (file.string().c_str(), _state->writer_info, _state->audio_desc); - if (ASDCP_FAILURE (r)) { - boost::throw_exception (FileError ("could not open audio MXF for writing", file.string(), r)); - } - - _sound_mxf->set_file (file); -} - -void -SoundMXFWriter::write (float const * const * data, int frames) -{ - DCP_ASSERT (!_finalized); - - for (int i = 0; i < frames; ++i) { - - byte_t* out = _state->frame_buffer.Data() + _frame_buffer_offset; - - /* Write one sample per channel */ - for (int j = 0; j < _sound_mxf->channels(); ++j) { - int32_t const s = data[j][i] * (1 << 23); - *out++ = (s & 0xff); - *out++ = (s & 0xff00) >> 8; - *out++ = (s & 0xff0000) >> 16; - } - _frame_buffer_offset += 3 * _sound_mxf->channels(); - - 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())) { - write_current_frame (); - _frame_buffer_offset = 0; - memset (_state->frame_buffer.Data(), 0, _state->frame_buffer.Capacity()); - } - } -} - -void -SoundMXFWriter::write_current_frame () -{ - ASDCP::Result_t const r = _state->mxf_writer.WriteFrame (_state->frame_buffer, _encryption_context, 0); - if (ASDCP_FAILURE (r)) { - boost::throw_exception (MiscError (String::compose ("could not write audio MXF frame (%1)", int (r)))); - } - - ++_frames_written; -} - -void -SoundMXFWriter::finalize () -{ - if (_frame_buffer_offset > 0) { - write_current_frame (); - } - - if (ASDCP_FAILURE (_state->mxf_writer.Finalize())) { - boost::throw_exception (MiscError ("could not finalise audio MXF")); - } - - _sound_mxf->_intrinsic_duration = _frames_written; - MXFWriter::finalize (); -} diff --git a/src/sound_mxf_writer.h b/src/sound_mxf_writer.h deleted file mode 100644 index d79c60db..00000000 --- a/src/sound_mxf_writer.h +++ /dev/null @@ -1,68 +0,0 @@ -/* - Copyright (C) 2012-2014 Carl Hetherington - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -*/ - -/** @file src/sound_mxf_writer.h - * @brief SoundMXFWriter class. - */ - -#include "mxf_writer.h" -#include "types.h" -#include -#include - -namespace dcp { - -class SoundFrame; -class SoundMXF; - -/** @class SoundMXFWriter - * @brief A helper class for writing to SoundMXFs. - * - * Objects of this class can only be created with SoundMXF::start_write(). - * - * Sound samples can be written to the SoundMXF by calling write() with - * a buffer of float values. finalize() must be called after the last samples - * have been written. - */ -class SoundMXFWriter : public MXFWriter -{ -public: - void write (float const * const *, int); - void finalize (); - -private: - friend class SoundMXF; - - SoundMXFWriter (SoundMXF *, boost::filesystem::path, Standard standard); - - void write_current_frame (); - - /* do this with an opaque pointer so we don't have to include - ASDCP headers - */ - - struct ASDCPState; - boost::shared_ptr _state; - - SoundMXF* _sound_mxf; - int _frame_buffer_offset; -}; - -} - diff --git a/src/stereo_picture_asset.cc b/src/stereo_picture_asset.cc new file mode 100644 index 00000000..452c3675 --- /dev/null +++ b/src/stereo_picture_asset.cc @@ -0,0 +1,140 @@ +/* + Copyright (C) 2012-2014 Carl Hetherington + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#include "AS_DCP.h" +#include "stereo_picture_asset.h" +#include "stereo_picture_frame.h" +#include "exceptions.h" +#include "stereo_picture_asset_writer.h" +#include "dcp_assert.h" + +using std::string; +using std::pair; +using std::make_pair; +using boost::shared_ptr; +using boost::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)); + } + + ASDCP::JP2K::PictureDescriptor desc; + if (ASDCP_FAILURE (reader.FillPictureDescriptor (desc))) { + boost::throw_exception (DCPReadError ("could not read video MXF information")); + } + + read_picture_descriptor (desc); + + ASDCP::WriterInfo info; + if (ASDCP_FAILURE (reader.FillWriterInfo (info))) { + boost::throw_exception (DCPReadError ("could not read video MXF information")); + } + + _id = read_writer_info (info); +} + +StereoPictureAsset::StereoPictureAsset (Fraction edit_rate) + : PictureAsset + (edit_rate) +{ + +} + +shared_ptr +StereoPictureAsset::get_frame (int n) const +{ + return shared_ptr (new StereoPictureFrame (file().string(), n)); +} + +shared_ptr +StereoPictureAsset::start_write (boost::filesystem::path file, Standard standard, bool overwrite) +{ + return shared_ptr (new StereoPictureAssetWriter (this, file, standard, overwrite)); +} + +bool +StereoPictureAsset::equals (shared_ptr other, EqualityOptions opt, NoteHandler note) const +{ + ASDCP::JP2K::MXFSReader reader_A; + 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)); + } + + ASDCP::JP2K::MXFSReader 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", file().string(), r)); + } + + ASDCP::JP2K::PictureDescriptor desc_A; + if (ASDCP_FAILURE (reader_A.FillPictureDescriptor (desc_A))) { + boost::throw_exception (DCPReadError ("could not read video MXF information")); + } + ASDCP::JP2K::PictureDescriptor desc_B; + if (ASDCP_FAILURE (reader_B.FillPictureDescriptor (desc_B))) { + boost::throw_exception (DCPReadError ("could not read video MXF information")); + } + + if (!descriptor_equals (desc_A, desc_B, note)) { + return false; + } + + shared_ptr other_picture = dynamic_pointer_cast (other); + DCP_ASSERT (other_picture); + + for (int i = 0; i < _intrinsic_duration; ++i) { + shared_ptr frame_A; + shared_ptr frame_B; + try { + frame_A = get_frame (i); + frame_B = other_picture->get_frame (i); + } catch (DCPReadError& e) { + /* If there was a problem reading the frame data we'll just assume + the two frames are not equal. + */ + note (DCP_ERROR, e.what ()); + return false; + } + + if (!frame_buffer_equals ( + i, opt, note, + frame_A->left_j2k_data(), frame_A->left_j2k_size(), + frame_B->left_j2k_data(), frame_B->left_j2k_size() + )) { + return false; + } + + if (!frame_buffer_equals ( + i, opt, note, + frame_A->right_j2k_data(), frame_A->right_j2k_size(), + frame_B->right_j2k_data(), frame_B->right_j2k_size() + )) { + return false; + } + } + + return true; +} diff --git a/src/stereo_picture_asset.h b/src/stereo_picture_asset.h new file mode 100644 index 00000000..2fe893de --- /dev/null +++ b/src/stereo_picture_asset.h @@ -0,0 +1,48 @@ +/* + Copyright (C) 2012-2015 Carl Hetherington + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#ifndef LIBDCP_STEREO_PICTURE_ASSET_H +#define LIBDCP_STEREO_PICTURE_ASSET_H + +#include "picture_asset.h" + +namespace dcp { + +/** A 3D (stereoscopic) picture asset */ +class StereoPictureAsset : public PictureAsset +{ +public: + StereoPictureAsset (boost::filesystem::path file); + StereoPictureAsset (Fraction edit_rate); + + /** Start a progressive write to a StereoPictureAsset */ + boost::shared_ptr start_write (boost::filesystem::path file, Standard, bool); + + bool equals ( + boost::shared_ptr other, + EqualityOptions opt, + NoteHandler note + ) const; + + boost::shared_ptr get_frame (int n) const; +}; + +} + +#endif diff --git a/src/stereo_picture_asset_writer.cc b/src/stereo_picture_asset_writer.cc new file mode 100644 index 00000000..be265d1e --- /dev/null +++ b/src/stereo_picture_asset_writer.cc @@ -0,0 +1,123 @@ +/* + Copyright (C) 2012-2015 Carl Hetherington + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#include "stereo_picture_asset_writer.h" +#include "exceptions.h" +#include "dcp_assert.h" +#include "picture_asset.h" +#include "AS_DCP.h" +#include "KM_fileio.h" + +#include "picture_asset_writer_common.cc" + +using std::istream; +using std::ostream; +using std::string; +using boost::shared_ptr; +using namespace dcp; + +struct StereoPictureAssetWriter::ASDCPState : public ASDCPStateBase +{ + ASDCP::JP2K::MXFSWriter mxf_writer; +}; + +StereoPictureAssetWriter::StereoPictureAssetWriter (PictureAsset* mxf, boost::filesystem::path file, Standard standard, bool overwrite) + : PictureAssetWriter (mxf, file, standard, overwrite) + , _state (new StereoPictureAssetWriter::ASDCPState) + , _next_eye (EYE_LEFT) +{ + +} + +void +StereoPictureAssetWriter::start (uint8_t* data, int size) +{ + dcp::start (this, _state, _standard, _picture_asset, data, 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* data, int size) +{ + DCP_ASSERT (!_finalized); + + if (!_started) { + start (data, size); + } + + 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; + Kumu::Result_t r = _state->mxf_writer.WriteFrame ( + _state->frame_buffer, + _next_eye == EYE_LEFT ? ASDCP::JP2K::SP_LEFT : ASDCP::JP2K::SP_RIGHT, + _encryption_context, + 0, + &hash + ); + + 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; + + if (_next_eye == EYE_LEFT) { + ++_frames_written; + } + + 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)); + } + + _next_eye = _next_eye == EYE_LEFT ? EYE_RIGHT : EYE_LEFT; + if (_next_eye == EYE_LEFT) { + ++_frames_written; + } +} + +void +StereoPictureAssetWriter::finalize () +{ + Kumu::Result_t r = _state->mxf_writer.Finalize(); + if (ASDCP_FAILURE (r)) { + boost::throw_exception (MXFFileError ("error in finalizing video MXF", _file.string(), r)); + } + + _picture_asset->_intrinsic_duration = _frames_written; + PictureAssetWriter::finalize (); +} diff --git a/src/stereo_picture_asset_writer.h b/src/stereo_picture_asset_writer.h new file mode 100644 index 00000000..bd41b45e --- /dev/null +++ b/src/stereo_picture_asset_writer.h @@ -0,0 +1,67 @@ +/* + Copyright (C) 2012-2014 Carl Hetherington + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#include "picture_asset_writer.h" +#include "types.h" +#include +#include +#include +#include +#include + +namespace dcp { + +/** A helper class for writing to StereoPictureAssets progressively (i.e. writing frame-by-frame, + * rather than giving libdcp all the frames in one go). + * + * Objects of this class can only be created with StereoPictureAsset::start_write(). + * + * Frames can be written to the MonoPictureAsset by calling write() with a JPEG2000 image + * (a verbatim .j2c file). finalize() must be called after the last frame has been written. + * The action of finalize() can't be done in MonoPictureAssetWriter's destructor as it may + * throw an exception. + */ +class StereoPictureAssetWriter : public PictureAssetWriter +{ +public: + /** 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 write (uint8_t* data, int size); + void fake_write (int size); + void finalize (); + +private: + friend class StereoPictureAsset; + + StereoPictureAssetWriter (PictureAsset *, boost::filesystem::path file, Standard, bool); + void start (uint8_t *, int); + + /* do this with an opaque pointer so we don't have to include + ASDCP headers + */ + + struct ASDCPState; + boost::shared_ptr _state; + + dcp::Eye _next_eye; +}; + +} diff --git a/src/stereo_picture_frame.cc b/src/stereo_picture_frame.cc index 3ee08303..855795eb 100644 --- a/src/stereo_picture_frame.cc +++ b/src/stereo_picture_frame.cc @@ -37,19 +37,19 @@ using namespace dcp; * @param mxf_path Path to the asset's MXF file. * @param n Frame within the asset, not taking EntryPoint into account. */ -StereoPictureFrame::StereoPictureFrame (boost::filesystem::path mxf_path, int n) +StereoPictureFrame::StereoPictureFrame (boost::filesystem::path path, int n) { ASDCP::JP2K::MXFSReader reader; - Kumu::Result_t r = reader.OpenRead (mxf_path.string().c_str()); + Kumu::Result_t r = reader.OpenRead (path.string().c_str()); if (ASDCP_FAILURE (r)) { - boost::throw_exception (FileError ("could not open MXF file for reading", mxf_path, r)); + boost::throw_exception (FileError ("could not open MXF file for reading", path, r)); } /* XXX: unfortunate guesswork on this buffer size */ _buffer = new ASDCP::JP2K::SFrameBuffer (4 * Kumu::Megabyte); if (ASDCP_FAILURE (reader.ReadFrame (n, *_buffer))) { - boost::throw_exception (DCPReadError (String::compose ("could not read video frame %1 of %2", n, mxf_path.string()))); + boost::throw_exception (DCPReadError (String::compose ("could not read video frame %1 of %2", n, path.string()))); } } diff --git a/src/stereo_picture_frame.h b/src/stereo_picture_frame.h index 0aeb6849..261bac93 100644 --- a/src/stereo_picture_frame.h +++ b/src/stereo_picture_frame.h @@ -38,7 +38,7 @@ class XYZImage; class StereoPictureFrame : public boost::noncopyable { public: - StereoPictureFrame (boost::filesystem::path mxf_path, int n); + StereoPictureFrame (boost::filesystem::path path, int n); StereoPictureFrame (); ~StereoPictureFrame (); diff --git a/src/stereo_picture_mxf.cc b/src/stereo_picture_mxf.cc deleted file mode 100644 index 0ac0cc83..00000000 --- a/src/stereo_picture_mxf.cc +++ /dev/null @@ -1,140 +0,0 @@ -/* - Copyright (C) 2012-2014 Carl Hetherington - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -*/ - -#include "AS_DCP.h" -#include "stereo_picture_mxf.h" -#include "stereo_picture_frame.h" -#include "exceptions.h" -#include "stereo_picture_mxf_writer.h" -#include "dcp_assert.h" - -using std::string; -using std::pair; -using std::make_pair; -using boost::shared_ptr; -using boost::dynamic_pointer_cast; -using namespace dcp; - -StereoPictureMXF::StereoPictureMXF (boost::filesystem::path file) - : PictureMXF (file) -{ - ASDCP::JP2K::MXFSReader reader; - Kumu::Result_t r = reader.OpenRead (file.string().c_str()); - if (ASDCP_FAILURE (r)) { - boost::throw_exception (MXFFileError ("could not open MXF file for reading", file.string(), r)); - } - - ASDCP::JP2K::PictureDescriptor desc; - if (ASDCP_FAILURE (reader.FillPictureDescriptor (desc))) { - boost::throw_exception (DCPReadError ("could not read video MXF information")); - } - - read_picture_descriptor (desc); - - ASDCP::WriterInfo info; - if (ASDCP_FAILURE (reader.FillWriterInfo (info))) { - boost::throw_exception (DCPReadError ("could not read video MXF information")); - } - - _id = read_writer_info (info); -} - -StereoPictureMXF::StereoPictureMXF (Fraction edit_rate) - : PictureMXF - (edit_rate) -{ - -} - -shared_ptr -StereoPictureMXF::get_frame (int n) const -{ - return shared_ptr (new StereoPictureFrame (file().string(), n)); -} - -shared_ptr -StereoPictureMXF::start_write (boost::filesystem::path file, Standard standard, bool overwrite) -{ - return shared_ptr (new StereoPictureMXFWriter (this, file, standard, overwrite)); -} - -bool -StereoPictureMXF::equals (shared_ptr other, EqualityOptions opt, NoteHandler note) const -{ - ASDCP::JP2K::MXFSReader reader_A; - 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)); - } - - ASDCP::JP2K::MXFSReader 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", file().string(), r)); - } - - ASDCP::JP2K::PictureDescriptor desc_A; - if (ASDCP_FAILURE (reader_A.FillPictureDescriptor (desc_A))) { - boost::throw_exception (DCPReadError ("could not read video MXF information")); - } - ASDCP::JP2K::PictureDescriptor desc_B; - if (ASDCP_FAILURE (reader_B.FillPictureDescriptor (desc_B))) { - boost::throw_exception (DCPReadError ("could not read video MXF information")); - } - - if (!descriptor_equals (desc_A, desc_B, note)) { - return false; - } - - shared_ptr other_picture = dynamic_pointer_cast (other); - DCP_ASSERT (other_picture); - - for (int i = 0; i < _intrinsic_duration; ++i) { - shared_ptr frame_A; - shared_ptr frame_B; - try { - frame_A = get_frame (i); - frame_B = other_picture->get_frame (i); - } catch (DCPReadError& e) { - /* If there was a problem reading the frame data we'll just assume - the two frames are not equal. - */ - note (DCP_ERROR, e.what ()); - return false; - } - - if (!frame_buffer_equals ( - i, opt, note, - frame_A->left_j2k_data(), frame_A->left_j2k_size(), - frame_B->left_j2k_data(), frame_B->left_j2k_size() - )) { - return false; - } - - if (!frame_buffer_equals ( - i, opt, note, - frame_A->right_j2k_data(), frame_A->right_j2k_size(), - frame_B->right_j2k_data(), frame_B->right_j2k_size() - )) { - return false; - } - } - - return true; -} diff --git a/src/stereo_picture_mxf.h b/src/stereo_picture_mxf.h deleted file mode 100644 index 9a094d19..00000000 --- a/src/stereo_picture_mxf.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - Copyright (C) 2012-2014 Carl Hetherington - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -*/ - -#ifndef LIBDCP_STEREO_PICTURE_MXF_H -#define LIBDCP_STEREO_PICTURE_MXF_H - -#include "picture_mxf.h" - -namespace dcp { - -/** A 3D (stereoscopic) picture asset */ -class StereoPictureMXF : public PictureMXF -{ -public: - StereoPictureMXF (boost::filesystem::path file); - StereoPictureMXF (Fraction edit_rate); - - /** Start a progressive write to a StereoPictureMXF */ - boost::shared_ptr start_write (boost::filesystem::path file, Standard, bool); - - bool equals ( - boost::shared_ptr other, - EqualityOptions opt, - NoteHandler note - ) const; - - boost::shared_ptr get_frame (int n) const; -}; - -} - -#endif diff --git a/src/stereo_picture_mxf_writer.cc b/src/stereo_picture_mxf_writer.cc deleted file mode 100644 index 7a65556f..00000000 --- a/src/stereo_picture_mxf_writer.cc +++ /dev/null @@ -1,123 +0,0 @@ -/* - Copyright (C) 2012-2014 Carl Hetherington - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -*/ - -#include "stereo_picture_mxf_writer.h" -#include "exceptions.h" -#include "dcp_assert.h" -#include "picture_mxf.h" -#include "AS_DCP.h" -#include "KM_fileio.h" - -#include "picture_mxf_writer_common.cc" - -using std::istream; -using std::ostream; -using std::string; -using boost::shared_ptr; -using namespace dcp; - -struct StereoPictureMXFWriter::ASDCPState : public ASDCPStateBase -{ - ASDCP::JP2K::MXFSWriter mxf_writer; -}; - -StereoPictureMXFWriter::StereoPictureMXFWriter (PictureMXF* mxf, boost::filesystem::path file, Standard standard, bool overwrite) - : PictureMXFWriter (mxf, file, standard, overwrite) - , _state (new StereoPictureMXFWriter::ASDCPState) - , _next_eye (EYE_LEFT) -{ - -} - -void -StereoPictureMXFWriter::start (uint8_t* data, int size) -{ - dcp::start (this, _state, _standard, _picture_mxf, data, size); - _picture_mxf->set_frame_rate (Fraction (_picture_mxf->edit_rate().numerator * 2, _picture_mxf->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 -StereoPictureMXFWriter::write (uint8_t* data, int size) -{ - DCP_ASSERT (!_finalized); - - if (!_started) { - start (data, size); - } - - 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; - Kumu::Result_t r = _state->mxf_writer.WriteFrame ( - _state->frame_buffer, - _next_eye == EYE_LEFT ? ASDCP::JP2K::SP_LEFT : ASDCP::JP2K::SP_RIGHT, - _encryption_context, - 0, - &hash - ); - - 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; - - if (_next_eye == EYE_LEFT) { - ++_frames_written; - } - - return FrameInfo (before_offset, _state->mxf_writer.Tell() - before_offset, hash); -} - -void -StereoPictureMXFWriter::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)); - } - - _next_eye = _next_eye == EYE_LEFT ? EYE_RIGHT : EYE_LEFT; - if (_next_eye == EYE_LEFT) { - ++_frames_written; - } -} - -void -StereoPictureMXFWriter::finalize () -{ - Kumu::Result_t r = _state->mxf_writer.Finalize(); - if (ASDCP_FAILURE (r)) { - boost::throw_exception (MXFFileError ("error in finalizing video MXF", _file.string(), r)); - } - - _picture_mxf->_intrinsic_duration = _frames_written; - PictureMXFWriter::finalize (); -} diff --git a/src/stereo_picture_mxf_writer.h b/src/stereo_picture_mxf_writer.h deleted file mode 100644 index 5491a64d..00000000 --- a/src/stereo_picture_mxf_writer.h +++ /dev/null @@ -1,67 +0,0 @@ -/* - Copyright (C) 2012-2014 Carl Hetherington - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -*/ - -#include "picture_mxf_writer.h" -#include "types.h" -#include -#include -#include -#include -#include - -namespace dcp { - -/** A helper class for writing to StereoPictureAssets progressively (i.e. writing frame-by-frame, - * rather than giving libdcp all the frames in one go). - * - * Objects of this class can only be created with StereoPictureAsset::start_write(). - * - * Frames can be written to the MonoPictureAsset by calling write() with a JPEG2000 image - * (a verbatim .j2c file). finalize() must be called after the last frame has been written. - * The action of finalize() can't be done in MonoPictureAssetWriter's destructor as it may - * throw an exception. - */ -class StereoPictureMXFWriter : public PictureMXFWriter -{ -public: - /** 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 write (uint8_t* data, int size); - void fake_write (int size); - void finalize (); - -private: - friend class StereoPictureMXF; - - StereoPictureMXFWriter (PictureMXF *, boost::filesystem::path file, Standard, bool); - void start (uint8_t *, int); - - /* do this with an opaque pointer so we don't have to include - ASDCP headers - */ - - struct ASDCPState; - boost::shared_ptr _state; - - dcp::Eye _next_eye; -}; - -} diff --git a/src/types.h b/src/types.h index a8e63faf..626666b4 100644 --- a/src/types.h +++ b/src/types.h @@ -160,7 +160,6 @@ struct EqualityOptions , max_std_dev_pixel_error (0) , max_audio_sample_error (0) , cpl_annotation_texts_can_differ (false) - , mxf_filenames_can_differ (false) , reel_annotation_texts_can_differ (false) , reel_hashes_can_differ (false) {} @@ -173,8 +172,6 @@ struct EqualityOptions int max_audio_sample_error; /** true if the nodes of CPLs are allowed to differ */ bool cpl_annotation_texts_can_differ; - /** true if MXF file leafnames are allowed to differ */ - bool mxf_filenames_can_differ; /** true if the nodes of Reels are allowed to differ */ bool reel_annotation_texts_can_differ; /** true if es in Reels can differ */ diff --git a/src/wscript b/src/wscript index 54f3a03b..ac3d9b0c 100644 --- a/src/wscript +++ b/src/wscript @@ -24,14 +24,14 @@ def build(bld): local_time.cc metadata.cc modified_gamma_transfer_function.cc - mono_picture_mxf.cc - mono_picture_mxf_writer.cc + mono_picture_asset.cc + mono_picture_asset_writer.cc mono_picture_frame.cc mxf.cc - mxf_writer.cc + asset_writer.cc object.cc - picture_mxf.cc - picture_mxf_writer.cc + picture_asset.cc + picture_asset_writer.cc reel.cc reel_asset.cc reel_mono_picture_asset.cc @@ -44,11 +44,11 @@ def build(bld): signer.cc smpte_load_font_node.cc smpte_subtitle_asset.cc - sound_mxf.cc - sound_mxf_writer.cc + sound_asset.cc + sound_asset_writer.cc sound_frame.cc - stereo_picture_mxf.cc - stereo_picture_mxf_writer.cc + stereo_picture_asset.cc + stereo_picture_asset_writer.cc stereo_picture_frame.cc subtitle_node.cc subtitle_asset.cc @@ -83,14 +83,14 @@ def build(bld): load_font_node.h local_time.h metadata.h - mono_picture_mxf.h + mono_picture_asset.h mono_picture_frame.h modified_gamma_transfer_function.h mxf.h - mxf_writer.h + asset_writer.h object.h - picture_mxf.h - picture_mxf_writer.h + picture_asset.h + picture_asset_writer.h raw_convert.h rgb_xyz.h reel.h @@ -106,9 +106,9 @@ def build(bld): smpte_load_font_node.h smpte_subtitle_asset.h sound_frame.h - sound_mxf.h - sound_mxf_writer.h - stereo_picture_mxf.h + sound_asset.h + sound_asset_writer.h + stereo_picture_asset.h stereo_picture_frame.h subtitle_node.h subtitle_asset.h -- cgit v1.2.3