#include "dcp.h"
#include "cpl.h"
-#include "mono_picture_mxf.h"
-#include "mono_picture_mxf_writer.h"
-#include "sound_mxf.h"
-#include "sound_mxf_writer.h"
+#include "mono_picture_asset.h"
+#include "mono_picture_asset_writer.h"
+#include "sound_asset.h"
+#include "sound_asset_writer.h"
#include "reel.h"
#include "file.h"
#include "reel_mono_picture_asset.h"
/* Create a directory to put the DCP in */
boost::filesystem::create_directory ("DCP");
- /* Make a picture MXF. This is a file which combines JPEG2000 files together to make
+ /* Make a picture asset. This is a file which combines JPEG2000 files together to make
up the video of the DCP. First, create the object, specifying a frame rate of 24 frames
per second.
*/
- boost::shared_ptr<dcp::MonoPictureMXF> picture_mxf (new dcp::MonoPictureMXF (dcp::Fraction (24, 1)));
+ boost::shared_ptr<dcp::MonoPictureAsset> picture_asset (new dcp::MonoPictureAsset (dcp::Fraction (24, 1)));
/* Start off a write to it */
- boost::shared_ptr<dcp::PictureMXFWriter> picture_writer = picture_mxf->start_write ("DCP/picture.mxf", dcp::SMPTE, false);
+ boost::shared_ptr<dcp::PictureAssetWriter> picture_writer = picture_asset->start_write ("DCP/picture.mxf", dcp::SMPTE, false);
/* Write 24 frames of the same JPEG2000 file */
dcp::File picture ("examples/help.j2c");
/* Now create a sound MXF. As before, create an object and a writer.
When creating the object we specify the sampling rate (48kHz) and the number of channels (2).
*/
- boost::shared_ptr<dcp::SoundMXF> sound_mxf (new dcp::SoundMXF (dcp::Fraction (24, 1), 48000, 2));
- boost::shared_ptr<dcp::SoundMXFWriter> sound_writer = sound_mxf->start_write ("DCP/sound.mxf", dcp::SMPTE);
+ boost::shared_ptr<dcp::SoundAsset> sound_asset (new dcp::SoundAsset (dcp::Fraction (24, 1), 48000, 2));
+ boost::shared_ptr<dcp::SoundAssetWriter> sound_writer = sound_asset->start_write ("DCP/sound.mxf", dcp::SMPTE);
/* Write some sine waves */
float* audio[2];
boost::shared_ptr<dcp::Reel> reel (new dcp::Reel ());
/* Add picture and sound to it. The zeros are the `entry points', i.e. the first
- (video) frame from the MXFs that the reel should play.
+ (video) frame from the assets that the reel should play.
*/
- reel->add (boost::shared_ptr<dcp::ReelPictureAsset> (new dcp::ReelMonoPictureAsset (picture_mxf, 0)));
- reel->add (boost::shared_ptr<dcp::ReelSoundAsset> (new dcp::ReelSoundAsset (sound_mxf, 0)));
+ reel->add (boost::shared_ptr<dcp::ReelPictureAsset> (new dcp::ReelMonoPictureAsset (picture_asset, 0)));
+ reel->add (boost::shared_ptr<dcp::ReelSoundAsset> (new dcp::ReelSoundAsset (sound_asset, 0)));
/* Make a CPL with this reel */
boost::shared_ptr<dcp::CPL> cpl (new dcp::CPL ("My film", dcp::FEATURE));
/* Write the DCP */
dcp::DCP dcp ("DCP");
dcp.add (cpl);
- dcp.add (picture_mxf);
- dcp.add (sound_mxf);
+ dcp.add (picture_asset);
+ dcp.add (sound_asset);
dcp.write_xml (dcp::SMPTE);
return 0;
/* If you are using an installed libdcp, these #includes would need to be changed to
#include <dcp/dcp.h>
-#include <dcp/picture_mxf.h>
+#include <dcp/picture_asset.h>
... etc. ...
*/
#include "reel.h"
#include "reel_picture_asset.h"
#include "mono_picture_frame.h"
-#include "mono_picture_mxf.h"
-#include "stereo_picture_mxf.h"
-#include "sound_mxf.h"
+#include "mono_picture_asset.h"
+#include "stereo_picture_asset.h"
+#include "sound_asset.h"
#include "subtitle_asset.h"
#include "xyz_image.h"
#include "colour_conversion.h"
std::list<boost::shared_ptr<dcp::Asset> > assets = dcp.assets ();
std::cout << "DCP has " << assets.size() << " assets.\n";
for (std::list<boost::shared_ptr<dcp::Asset> >::const_iterator i = assets.begin(); i != assets.end(); ++i) {
- if (boost::dynamic_pointer_cast<dcp::MonoPictureMXF> (*i)) {
+ if (boost::dynamic_pointer_cast<dcp::MonoPictureAsset> (*i)) {
std::cout << "2D picture\n";
- } else if (boost::dynamic_pointer_cast<dcp::StereoPictureMXF> (*i)) {
+ } else if (boost::dynamic_pointer_cast<dcp::StereoPictureAsset> (*i)) {
std::cout << "3D picture\n";
- } else if (boost::dynamic_pointer_cast<dcp::SoundMXF> (*i)) {
+ } else if (boost::dynamic_pointer_cast<dcp::SoundAsset> (*i)) {
std::cout << "Sound\n";
} else if (boost::dynamic_pointer_cast<dcp::SubtitleAsset> (*i)) {
std::cout << "Subtitle\n";
/* Take the first CPL */
boost::shared_ptr<dcp::CPL> cpl = dcp.cpls().front ();
- /* Get the MXF of the picture asset in the first reel */
- boost::shared_ptr<dcp::MonoPictureMXF> picture_mxf = boost::dynamic_pointer_cast<dcp::MonoPictureMXF> (cpl->reels().front()->main_picture()->mxf ());
+ /* Get the picture asset in the first reel */
+ boost::shared_ptr<dcp::MonoPictureAsset> picture_asset = boost::dynamic_pointer_cast<dcp::MonoPictureAsset> (
+ cpl->reels().front()->main_picture()->asset()
+ );
/* Get the 1000th frame of it */
- boost::shared_ptr<const dcp::MonoPictureFrame> picture_frame_j2k = picture_mxf->get_frame(999);
+ boost::shared_ptr<const dcp::MonoPictureFrame> picture_frame_j2k = picture_asset->get_frame(999);
/* Get the frame as an XYZ image */
boost::shared_ptr<const dcp::XYZImage> picture_image_xyz = picture_frame_j2k->xyz_image ();
--- /dev/null
+/*
+ Copyright (C) 2012-2015 Carl Hetherington <cth@carlh.net>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+/** @file src/asset_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;
+}
--- /dev/null
+/*
+ Copyright (C) 2012-2015 Carl Hetherington <cth@carlh.net>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+/** @file src/asset_writer.h
+ * @brief AssetWriter class.
+ */
+
+#ifndef LIBDCP_ASSET_WRITER_H
+#define LIBDCP_ASSET_WRITER_H
+
+#include <boost/filesystem.hpp>
+
+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
#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"
case ASDCP::ESS_MPEG2_VES:
throw DCPReadError ("MPEG2 video essences are not supported");
case ASDCP::ESS_JPEG_2000:
- _assets.push_back (shared_ptr<MonoPictureMXF> (new MonoPictureMXF (path)));
+ _assets.push_back (shared_ptr<MonoPictureAsset> (new MonoPictureAsset (path)));
break;
case ASDCP::ESS_PCM_24b_48k:
case ASDCP::ESS_PCM_24b_96k:
- _assets.push_back (shared_ptr<SoundMXF> (new SoundMXF (path)));
+ _assets.push_back (shared_ptr<SoundAsset> (new SoundAsset (path)));
break;
case ASDCP::ESS_JPEG_2000_S:
- _assets.push_back (shared_ptr<StereoPictureMXF> (new StereoPictureMXF (path)));
+ _assets.push_back (shared_ptr<StereoPictureAsset> (new StereoPictureAsset (path)));
break;
case ASDCP::ESS_TIMED_TEXT:
_assets.push_back (shared_ptr<SMPTESubtitleAsset> (new SMPTESubtitleAsset (path)));
/*
- Copyright (C) 2013-2014 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2013-2015 Carl Hetherington <cth@carlh.net>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
* 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
{
/** 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.
*/
*/
EncryptedKDM encrypt (boost::shared_ptr<const Signer> 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<DecryptedKDMKey> keys () const {
return _keys;
}
namespace dcp {
/** @class Key
- * @brief A key for decrypting/encrypting MXFs.
+ * @brief A key for decrypting/encrypting assets.
*/
class Key
{
--- /dev/null
+/*
+ Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#include "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<const MonoPictureFrame>
+MonoPictureAsset::get_frame (int n) const
+{
+ return shared_ptr<const MonoPictureFrame> (new MonoPictureFrame (_file, n, _decryption_context));
+}
+
+bool
+MonoPictureAsset::equals (shared_ptr<const Asset> other, EqualityOptions opt, NoteHandler note) const
+{
+ if (!dynamic_pointer_cast<const MonoPictureAsset> (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<const MonoPictureAsset> other_picture = dynamic_pointer_cast<const MonoPictureAsset> (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<const MonoPictureFrame> frame_A = get_frame (i);
+ shared_ptr<const MonoPictureFrame> 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<PictureAssetWriter>
+MonoPictureAsset::start_write (boost::filesystem::path file, Standard standard, bool overwrite)
+{
+ /* XXX: can't we use shared_ptr here? */
+ return shared_ptr<MonoPictureAssetWriter> (new MonoPictureAssetWriter (this, file, standard, overwrite));
+}
+
+string
+MonoPictureAsset::cpl_node_name () const
+{
+ return "MainPicture";
+}
--- /dev/null
+/*
+ Copyright (C) 2012-2015 Carl Hetherington <cth@carlh.net>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#ifndef LIBDCP_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<PictureAssetWriter> start_write (boost::filesystem::path, Standard standard, bool);
+
+ bool equals (
+ boost::shared_ptr<const Asset> other,
+ EqualityOptions opt,
+ NoteHandler note
+ ) const;
+
+ boost::shared_ptr<const MonoPictureFrame> get_frame (int n) const;
+
+private:
+ std::string cpl_node_name () const;
+};
+
+}
+
+#endif
--- /dev/null
+/*
+ Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+/** @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 ();
+}
+
--- /dev/null
+/*
+ Copyright (C) 2012-2015 Carl Hetherington <cth@carlh.net>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+/** @file src/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 <boost/shared_ptr.hpp>
+#include <boost/utility.hpp>
+#include <stdint.h>
+#include <string>
+#include <fstream>
+
+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<ASDCPState> _state;
+};
+
+}
+
+#endif
}
/** 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 */
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 ();
+++ /dev/null
-/*
- Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-*/
-
-#include "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<const MonoPictureFrame>
-MonoPictureMXF::get_frame (int n) const
-{
- return shared_ptr<const MonoPictureFrame> (new MonoPictureFrame (_file, n, _decryption_context));
-}
-
-bool
-MonoPictureMXF::equals (shared_ptr<const Asset> other, EqualityOptions opt, NoteHandler note) const
-{
- if (!dynamic_pointer_cast<const MonoPictureMXF> (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<const MonoPictureMXF> other_picture = dynamic_pointer_cast<const MonoPictureMXF> (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<const MonoPictureFrame> frame_A = get_frame (i);
- shared_ptr<const MonoPictureFrame> 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<PictureMXFWriter>
-MonoPictureMXF::start_write (boost::filesystem::path file, Standard standard, bool overwrite)
-{
- /* XXX: can't we use shared_ptr here? */
- return shared_ptr<MonoPictureMXFWriter> (new MonoPictureMXFWriter (this, file, standard, overwrite));
-}
-
-string
-MonoPictureMXF::cpl_node_name () const
-{
- return "MainPicture";
-}
+++ /dev/null
-/*
- Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-*/
-
-#ifndef LIBDCP_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<PictureMXFWriter> start_write (boost::filesystem::path, Standard standard, bool);
-
- bool equals (
- boost::shared_ptr<const Asset> other,
- EqualityOptions opt,
- NoteHandler note
- ) const;
-
- boost::shared_ptr<const MonoPictureFrame> get_frame (int n) const;
-
-private:
- std::string cpl_node_name () const;
-};
-
-}
-
-#endif
+++ /dev/null
-/*
- Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-*/
-
-/** @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 ();
-}
-
+++ /dev/null
-/*
- Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-*/
-
-/** @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 <boost/shared_ptr.hpp>
-#include <boost/utility.hpp>
-#include <stdint.h>
-#include <string>
-#include <fstream>
-
-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<ASDCPState> _state;
-};
-
-}
-
-#endif
{
class MXFMetadata;
-class PictureMXFWriter;
+class PictureAssetWriter;
/** @class MXF
* @brief Parent class for classes which represent MXF files.
protected:
template <class P, class Q>
- friend void start (PictureMXFWriter* writer, boost::shared_ptr<P> state, Standard standard, Q* mxf, uint8_t* data, int size);
+ friend void start (PictureAssetWriter* writer, boost::shared_ptr<P> state, Standard standard, Q* mxf, uint8_t* data, int size);
std::string read_writer_info (ASDCP::WriterInfo const &);
/** Fill in a ADSCP::WriteInfo struct.
+++ /dev/null
-/*
- Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-*/
-
-/** @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;
-}
+++ /dev/null
-/*
- Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-*/
-
-/** @file src/mxf_writer.h
- * @brief MXFWriter class.
- */
-
-#ifndef LIBDCP_MXF_WRITER_H
-#define LIBDCP_MXF_WRITER_H
-
-#include <boost/filesystem.hpp>
-
-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
--- /dev/null
+/*
+ Copyright (C) 2012-2015 Carl Hetherington <cth@carlh.net>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#include "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 <libxml++/nodes/element.h>
+#include <openjpeg.h>
+#include <boost/filesystem.hpp>
+#include <list>
+#include <stdexcept>
+#include <iostream>
+#include <sstream>
+
+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<XYZImage> image_A = decompress_j2k (const_cast<uint8_t*> (data_A), size_A, 0);
+ shared_ptr<XYZImage> image_B = decompress_j2k (const_cast<uint8_t*> (data_B), size_B, 0);
+
+ /* Compare them */
+
+ vector<int> 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<int>::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<int>::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);
+ }
+}
--- /dev/null
+/*
+ Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#ifndef LIBDCP_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 <openjpeg.h>
+
+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<PictureAssetWriter> 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
--- /dev/null
+/*
+ Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#include "KM_fileio.h"
+#include "picture_asset_writer.h"
+#include "exceptions.h"
+#include "picture_asset.h"
+#include "AS_DCP.h"
+#include <inttypes.h>
+#include <stdint.h>
+
+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);
+}
--- /dev/null
+/*
+ Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+/** @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 <boost/shared_ptr.hpp>
+#include <boost/utility.hpp>
+#include <stdint.h>
+#include <string>
+#include <fstream>
+
+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 <class P, class Q>
+ friend void start (PictureAssetWriter *, boost::shared_ptr<P>, Standard, Q *, uint8_t *, int);
+
+ PictureAssetWriter (PictureAsset *, boost::filesystem::path, Standard standard, bool);
+
+ PictureAsset* _picture_asset;
+ bool _started;
+ Standard _standard;
+ bool _overwrite;
+};
+
+}
+
+#endif
--- /dev/null
+/*
+ Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+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 <class P, class Q>
+void dcp::start (PictureAssetWriter* writer, shared_ptr<P> 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;
+}
+++ /dev/null
-/*
- Copyright (C) 2012-2015 Carl Hetherington <cth@carlh.net>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-*/
-
-#include "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 <libxml++/nodes/element.h>
-#include <openjpeg.h>
-#include <boost/filesystem.hpp>
-#include <list>
-#include <stdexcept>
-#include <iostream>
-#include <sstream>
-
-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<XYZImage> image_A = decompress_j2k (const_cast<uint8_t*> (data_A), size_A, 0);
- shared_ptr<XYZImage> image_B = decompress_j2k (const_cast<uint8_t*> (data_B), size_B, 0);
-
- /* Compare them */
-
- vector<int> 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<int>::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<int>::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);
- }
-}
+++ /dev/null
-/*
- Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-*/
-
-#ifndef LIBDCP_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 <openjpeg.h>
-
-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<PictureMXFWriter> 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
+++ /dev/null
-/*
- Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-*/
-
-#include "KM_fileio.h"
-#include "picture_mxf_writer.h"
-#include "exceptions.h"
-#include "picture_mxf.h"
-#include "AS_DCP.h"
-#include <inttypes.h>
-#include <stdint.h>
-
-using std::istream;
-using std::ostream;
-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);
-}
+++ /dev/null
-/*
- Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-*/
-
-/** @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 <boost/shared_ptr.hpp>
-#include <boost/utility.hpp>
-#include <stdint.h>
-#include <string>
-#include <fstream>
-
-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 <class P, class Q>
- friend void start (PictureMXFWriter *, boost::shared_ptr<P>, Standard, Q *, uint8_t *, int);
-
- PictureMXFWriter (PictureMXF *, boost::filesystem::path, Standard standard, bool);
-
- PictureMXF* _picture_mxf;
- bool _started;
- Standard _standard;
- bool _overwrite;
-};
-
-}
-
-#endif
+++ /dev/null
-/*
- Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-*/
-
-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 <class P, class Q>
-void dcp::start (PictureMXFWriter* writer, shared_ptr<P> 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;
-}
#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"
for (list<DecryptedKDMKey>::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 ());
}
}
}
Reel::resolve_refs (list<shared_ptr<Object> > 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);
}
}
ReelAsset::ReelAsset ()
: Object (make_uuid ())
- , _asset (_id)
+ , _asset_ref (_id)
, _edit_rate (Fraction (24, 1))
, _intrinsic_duration (0)
, _entry_point (0)
*/
ReelAsset::ReelAsset (shared_ptr<Asset> 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)
ReelAsset::ReelAsset (shared_ptr<const cxml::Node> 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<int64_t> ("IntrinsicDuration"))
{
if (_id.length() > 9) {
_id = _id.substr (9);
- _asset.set_id (_id);
+ _asset_ref.set_id (_id);
}
}
a->add_child("IntrinsicDuration")->add_child_text (raw_convert<string> (_intrinsic_duration));
a->add_child("EntryPoint")->add_child_text (raw_convert<string> (_entry_point));
a->add_child("Duration")->add_child_text (raw_convert<string> (_duration));
- a->add_child("Hash")->add_child_text (_asset.object()->hash ());
+ a->add_child("Hash")->add_child_text (_asset_ref.object()->hash ());
}
pair<string, string>
}
}
- 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;
virtual bool equals (boost::shared_ptr<const ReelAsset>, EqualityOptions, NoteHandler) const;
/** @return a Ref to our actual asset */
- Ref<Asset>& asset () {
- return _asset;
+ Ref<Asset>& asset_ref () {
+ return _asset_ref;
}
int64_t entry_point () const {
/** Reference to the asset (MXF or XML file) that this reel entry
* applies to.
*/
- Ref<Asset> _asset;
+ Ref<Asset> _asset_ref;
private:
/*
- Copyright (C) 2014 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2014-2015 Carl Hetherington <cth@carlh.net>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
*/
#include "reel_mono_picture_asset.h"
-#include "mono_picture_mxf.h"
+#include "mono_picture_asset.h"
#include <libcxml/cxml.h>
using std::string;
}
-ReelMonoPictureAsset::ReelMonoPictureAsset (boost::shared_ptr<MonoPictureMXF> mxf, int64_t entry_point)
- : ReelPictureAsset (mxf, entry_point)
+ReelMonoPictureAsset::ReelMonoPictureAsset (boost::shared_ptr<MonoPictureAsset> asset, int64_t entry_point)
+ : ReelPictureAsset (asset, entry_point)
{
}
/*
- Copyright (C) 2014 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2014-2015 Carl Hetherington <cth@carlh.net>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
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<MonoPictureMXF> content, int64_t entry_point);
+ ReelMonoPictureAsset (boost::shared_ptr<MonoPictureAsset> asset, int64_t entry_point);
ReelMonoPictureAsset (boost::shared_ptr<const cxml::Node>);
private:
{
public:
ReelMXFAsset ();
- ReelMXFAsset (boost::shared_ptr<Asset> mxf, boost::optional<std::string> key_id, Fraction edit_rate, int64_t intrinsic_duration, int64_t entry_point);
+ ReelMXFAsset (boost::shared_ptr<Asset> asset, boost::optional<std::string> key_id, Fraction edit_rate, int64_t intrinsic_duration, int64_t entry_point);
ReelMXFAsset (boost::shared_ptr<const cxml::Node>);
/** @return the 4-character key type for this MXF (MDIK, MDAK, etc.) */
*/
#include "reel_picture_asset.h"
-#include "picture_mxf.h"
+#include "picture_asset.h"
#include "dcp_assert.h"
#include "compose.hpp"
#include <libcxml/cxml.h>
}
-ReelPictureAsset::ReelPictureAsset (shared_ptr<PictureMXF> asset, int64_t entry_point)
+ReelPictureAsset::ReelPictureAsset (shared_ptr<PictureAsset> 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 ())
#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<PictureMXF> asset, int64_t entry_point);
+ ReelPictureAsset (boost::shared_ptr<PictureAsset> asset, int64_t entry_point);
ReelPictureAsset (boost::shared_ptr<const cxml::Node>);
virtual void write_to_cpl (xmlpp::Node* node, Standard standard) const;
virtual bool equals (boost::shared_ptr<const ReelAsset>, EqualityOptions, NoteHandler) const;
- /** @return the PictureMXF that this object refers to */
- boost::shared_ptr<PictureMXF> mxf () {
- return boost::dynamic_pointer_cast<PictureMXF> (_asset.object ());
+ /** @return the PictureAsset that this object refers to */
+ boost::shared_ptr<PictureAsset> asset () {
+ return boost::dynamic_pointer_cast<PictureAsset> (_asset_ref.object ());
}
/** @return picture frame rate */
using boost::shared_ptr;
using namespace dcp;
-ReelSoundAsset::ReelSoundAsset (shared_ptr<SoundMXF> asset, int64_t entry_point)
+ReelSoundAsset::ReelSoundAsset (shared_ptr<SoundAsset> asset, int64_t entry_point)
: ReelMXFAsset (asset, asset->key_id(), asset->edit_rate(), asset->intrinsic_duration(), entry_point)
{
*/
#include "reel_mxf_asset.h"
-#include "sound_mxf.h"
+#include "sound_asset.h"
#include <boost/shared_ptr.hpp>
#include <string>
class ReelSoundAsset : public ReelMXFAsset
{
public:
- ReelSoundAsset (boost::shared_ptr<dcp::SoundMXF> content, int64_t entry_point);
+ ReelSoundAsset (boost::shared_ptr<dcp::SoundAsset> content, int64_t entry_point);
ReelSoundAsset (boost::shared_ptr<const cxml::Node>);
void write_to_cpl (xmlpp::Node* node, Standard standard) const;
- /** @return the SoundMXF that this object refers to */
- boost::shared_ptr<SoundMXF> mxf () {
- return boost::dynamic_pointer_cast<SoundMXF> (_asset.object ());
+ /** @return the SoundAsset that this object refers to */
+ boost::shared_ptr<SoundAsset> asset () {
+ return boost::dynamic_pointer_cast<SoundAsset> (_asset_ref.object ());
}
- /** @return the SoundMXF that this object refers to */
- boost::shared_ptr<const SoundMXF> mxf () const {
- return boost::dynamic_pointer_cast<const SoundMXF> (_asset.object ());
+ /** @return the SoundAsset that this object refers to */
+ boost::shared_ptr<const SoundAsset> asset () const {
+ return boost::dynamic_pointer_cast<const SoundAsset> (_asset_ref.object ());
}
private:
*/
#include "reel_stereo_picture_asset.h"
-#include "stereo_picture_mxf.h"
+#include "stereo_picture_asset.h"
#include <libcxml/cxml.h>
using std::string;
}
-ReelStereoPictureAsset::ReelStereoPictureAsset (boost::shared_ptr<StereoPictureMXF> mxf, int64_t entry_point)
+ReelStereoPictureAsset::ReelStereoPictureAsset (boost::shared_ptr<StereoPictureAsset> mxf, int64_t entry_point)
: ReelPictureAsset (mxf, entry_point)
{
namespace dcp {
-class StereoPictureMXF;
+class StereoPictureAsset;
/** @class ReelStereoPictureAsset
* @brief Part of a Reel's description which refers to a stereoscopic picture MXF.
{
public:
ReelStereoPictureAsset ();
- ReelStereoPictureAsset (boost::shared_ptr<StereoPictureMXF> content, int64_t entry_point);
+ ReelStereoPictureAsset (boost::shared_ptr<StereoPictureAsset> content, int64_t entry_point);
ReelStereoPictureAsset (boost::shared_ptr<const cxml::Node>);
private:
ReelSubtitleAsset (boost::shared_ptr<const cxml::Node>);
boost::shared_ptr<SubtitleAsset> subtitle_asset () const {
- return boost::dynamic_pointer_cast<SubtitleAsset> (_asset.object ());
+ return boost::dynamic_pointer_cast<SubtitleAsset> (_asset_ref.object ());
}
private:
--- /dev/null
+/*
+ Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+/** @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 <libxml++/nodes/element.h>
+#include <boost/filesystem.hpp>
+#include <iostream>
+#include <stdexcept>
+
+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<const Asset> 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<const SoundFrame>
+SoundAsset::get_frame (int n) const
+{
+ /* XXX: should add on entry point here? */
+ return shared_ptr<const SoundFrame> (new SoundFrame (file(), n, _decryption_context));
+}
+
+shared_ptr<SoundAssetWriter>
+SoundAsset::start_write (boost::filesystem::path file, Standard standard)
+{
+ /* XXX: can't we use a shared_ptr here? */
+ return shared_ptr<SoundAssetWriter> (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);
+ }
+}
--- /dev/null
+/*
+ Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+/** @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<SoundAssetWriter> start_write (boost::filesystem::path file, Standard standard);
+
+ bool equals (
+ boost::shared_ptr<const Asset> other,
+ EqualityOptions opt,
+ NoteHandler note
+ ) const;
+
+ boost::shared_ptr<const SoundFrame> 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
--- /dev/null
+/*
+ Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#include "sound_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 ();
+}
--- /dev/null
+/*
+ Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+/** @file src/sound_asset_writer.h
+ * @brief SoundAssetWriter class.
+ */
+
+#include "asset_writer.h"
+#include "types.h"
+#include <boost/shared_ptr.hpp>
+#include <boost/filesystem.hpp>
+
+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<ASDCPState> _state;
+
+ SoundAsset* _sound_asset;
+ int _frame_buffer_offset;
+};
+
+}
+
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 */
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;
+++ /dev/null
-/*
- Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-*/
-
-/** @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 <libxml++/nodes/element.h>
-#include <boost/filesystem.hpp>
-#include <iostream>
-#include <stdexcept>
-
-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<const Asset> 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<const SoundFrame>
-SoundMXF::get_frame (int n) const
-{
- /* XXX: should add on entry point here? */
- return shared_ptr<const SoundFrame> (new SoundFrame (file(), n, _decryption_context));
-}
-
-shared_ptr<SoundMXFWriter>
-SoundMXF::start_write (boost::filesystem::path file, Standard standard)
-{
- /* XXX: can't we use a shared_ptr here? */
- return shared_ptr<SoundMXFWriter> (new SoundMXFWriter (this, 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);
- }
-}
+++ /dev/null
-/*
- Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-*/
-
-/** @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<SoundMXFWriter> start_write (boost::filesystem::path file, Standard standard);
-
- bool equals (
- boost::shared_ptr<const Asset> other,
- EqualityOptions opt,
- NoteHandler note
- ) const;
-
- boost::shared_ptr<const SoundFrame> 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
+++ /dev/null
-/*
- Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-*/
-
-#include "sound_mxf_writer.h"
-#include "sound_mxf.h"
-#include "exceptions.h"
-#include "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 ();
-}
+++ /dev/null
-/*
- Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-*/
-
-/** @file src/sound_mxf_writer.h
- * @brief SoundMXFWriter class.
- */
-
-#include "mxf_writer.h"
-#include "types.h"
-#include <boost/shared_ptr.hpp>
-#include <boost/filesystem.hpp>
-
-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<ASDCPState> _state;
-
- SoundMXF* _sound_mxf;
- int _frame_buffer_offset;
-};
-
-}
-
--- /dev/null
+/*
+ Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#include "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<const StereoPictureFrame>
+StereoPictureAsset::get_frame (int n) const
+{
+ return shared_ptr<const StereoPictureFrame> (new StereoPictureFrame (file().string(), n));
+}
+
+shared_ptr<PictureAssetWriter>
+StereoPictureAsset::start_write (boost::filesystem::path file, Standard standard, bool overwrite)
+{
+ return shared_ptr<StereoPictureAssetWriter> (new StereoPictureAssetWriter (this, file, standard, overwrite));
+}
+
+bool
+StereoPictureAsset::equals (shared_ptr<const Asset> 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<const StereoPictureAsset> other_picture = dynamic_pointer_cast<const StereoPictureAsset> (other);
+ DCP_ASSERT (other_picture);
+
+ for (int i = 0; i < _intrinsic_duration; ++i) {
+ shared_ptr<const StereoPictureFrame> frame_A;
+ shared_ptr<const StereoPictureFrame> 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;
+}
--- /dev/null
+/*
+ Copyright (C) 2012-2015 Carl Hetherington <cth@carlh.net>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#ifndef LIBDCP_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<PictureAssetWriter> start_write (boost::filesystem::path file, Standard, bool);
+
+ bool equals (
+ boost::shared_ptr<const Asset> other,
+ EqualityOptions opt,
+ NoteHandler note
+ ) const;
+
+ boost::shared_ptr<const StereoPictureFrame> get_frame (int n) const;
+};
+
+}
+
+#endif
--- /dev/null
+/*
+ Copyright (C) 2012-2015 Carl Hetherington <cth@carlh.net>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#include "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 ();
+}
--- /dev/null
+/*
+ Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#include "picture_asset_writer.h"
+#include "types.h"
+#include <boost/shared_ptr.hpp>
+#include <boost/utility.hpp>
+#include <stdint.h>
+#include <string>
+#include <fstream>
+
+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<ASDCPState> _state;
+
+ dcp::Eye _next_eye;
+};
+
+}
* @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())));
}
}
class StereoPictureFrame : public boost::noncopyable
{
public:
- StereoPictureFrame (boost::filesystem::path mxf_path, int n);
+ StereoPictureFrame (boost::filesystem::path path, int n);
StereoPictureFrame ();
~StereoPictureFrame ();
+++ /dev/null
-/*
- Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-*/
-
-#include "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<const StereoPictureFrame>
-StereoPictureMXF::get_frame (int n) const
-{
- return shared_ptr<const StereoPictureFrame> (new StereoPictureFrame (file().string(), n));
-}
-
-shared_ptr<PictureMXFWriter>
-StereoPictureMXF::start_write (boost::filesystem::path file, Standard standard, bool overwrite)
-{
- return shared_ptr<StereoPictureMXFWriter> (new StereoPictureMXFWriter (this, file, standard, overwrite));
-}
-
-bool
-StereoPictureMXF::equals (shared_ptr<const Asset> 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<const StereoPictureMXF> other_picture = dynamic_pointer_cast<const StereoPictureMXF> (other);
- DCP_ASSERT (other_picture);
-
- for (int i = 0; i < _intrinsic_duration; ++i) {
- shared_ptr<const StereoPictureFrame> frame_A;
- shared_ptr<const StereoPictureFrame> 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;
-}
+++ /dev/null
-/*
- Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-*/
-
-#ifndef LIBDCP_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<PictureMXFWriter> start_write (boost::filesystem::path file, Standard, bool);
-
- bool equals (
- boost::shared_ptr<const Asset> other,
- EqualityOptions opt,
- NoteHandler note
- ) const;
-
- boost::shared_ptr<const StereoPictureFrame> get_frame (int n) const;
-};
-
-}
-
-#endif
+++ /dev/null
-/*
- Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-*/
-
-#include "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 ();
-}
+++ /dev/null
-/*
- Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-*/
-
-#include "picture_mxf_writer.h"
-#include "types.h"
-#include <boost/shared_ptr.hpp>
-#include <boost/utility.hpp>
-#include <stdint.h>
-#include <string>
-#include <fstream>
-
-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<ASDCPState> _state;
-
- dcp::Eye _next_eye;
-};
-
-}
, 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)
{}
int max_audio_sample_error;
/** true if the <AnnotationText> 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 <AnnotationText> nodes of Reels are allowed to differ */
bool reel_annotation_texts_can_differ;
/** true if <Hash>es in Reels can differ */
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
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
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
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
#include "cpl.h"
#include "reel_mono_picture_asset.h"
-#include "mono_picture_mxf.h"
+#include "mono_picture_asset.h"
#include <libcxml/cxml.h>
#include <boost/test/unit_test.hpp>
{
shared_ptr<dcp::ReelMonoPictureAsset> pa (
new dcp::ReelMonoPictureAsset (
- shared_ptr<dcp::MonoPictureMXF> (new dcp::MonoPictureMXF ("test/ref/DCP/dcp_test1/video.mxf")),
+ shared_ptr<dcp::MonoPictureAsset> (new dcp::MonoPictureAsset ("test/ref/DCP/dcp_test1/video.mxf")),
0
)
);
#include "dcp.h"
#include "metadata.h"
#include "cpl.h"
-#include "mono_picture_mxf.h"
-#include "stereo_picture_mxf.h"
-#include "picture_mxf_writer.h"
-#include "sound_mxf_writer.h"
-#include "sound_mxf.h"
+#include "mono_picture_asset.h"
+#include "stereo_picture_asset.h"
+#include "picture_asset_writer.h"
+#include "sound_asset_writer.h"
+#include "sound_asset.h"
#include "reel.h"
#include "test.h"
#include "file.h"
cpl->set_content_version_label_text ("81fb54df-e1bf-4647-8788-ea7ba154375b_2012-07-17T04:45:18+00:00");
cpl->set_metadata (xml_meta);
- shared_ptr<dcp::MonoPictureMXF> mp (new dcp::MonoPictureMXF (dcp::Fraction (24, 1)));
+ shared_ptr<dcp::MonoPictureAsset> mp (new dcp::MonoPictureAsset (dcp::Fraction (24, 1)));
mp->set_metadata (mxf_meta);
- shared_ptr<dcp::PictureMXFWriter> picture_writer = mp->start_write ("build/test/DCP/dcp_test1/video.mxf", dcp::SMPTE, false);
+ shared_ptr<dcp::PictureAssetWriter> picture_writer = mp->start_write ("build/test/DCP/dcp_test1/video.mxf", dcp::SMPTE, false);
dcp::File j2c ("test/data/32x32_red_square.j2c");
for (int i = 0; i < 24; ++i) {
picture_writer->write (j2c.data (), j2c.size ());
}
picture_writer->finalize ();
- shared_ptr<dcp::SoundMXF> ms (new dcp::SoundMXF (dcp::Fraction (24, 1), 48000, 1));
+ shared_ptr<dcp::SoundAsset> ms (new dcp::SoundAsset (dcp::Fraction (24, 1), 48000, 1));
ms->set_metadata (mxf_meta);
- shared_ptr<dcp::SoundMXFWriter> sound_writer = ms->start_write ("build/test/DCP/dcp_test1/audio.mxf", dcp::SMPTE);
+ shared_ptr<dcp::SoundAssetWriter> sound_writer = ms->start_write ("build/test/DCP/dcp_test1/audio.mxf", dcp::SMPTE);
SF_INFO info;
info.format = 0;
cpl->set_content_version_label_text ("81fb54df-e1bf-4647-8788-ea7ba154375b_2012-07-17T04:45:18+00:00");
cpl->set_metadata (xml_meta);
- shared_ptr<dcp::StereoPictureMXF> mp (new dcp::StereoPictureMXF (dcp::Fraction (24, 1)));
+ shared_ptr<dcp::StereoPictureAsset> mp (new dcp::StereoPictureAsset (dcp::Fraction (24, 1)));
mp->set_metadata (mxf_meta);
- shared_ptr<dcp::PictureMXFWriter> picture_writer = mp->start_write ("build/test/DCP/dcp_test2/video.mxf", dcp::SMPTE, false);
+ shared_ptr<dcp::PictureAssetWriter> picture_writer = mp->start_write ("build/test/DCP/dcp_test2/video.mxf", dcp::SMPTE, false);
dcp::File j2c ("test/data/32x32_red_square.j2c");
for (int i = 0; i < 24; ++i) {
/* Left */
}
picture_writer->finalize ();
- shared_ptr<dcp::SoundMXF> ms (new dcp::SoundMXF (dcp::Fraction (24, 1), 48000, 1));
+ shared_ptr<dcp::SoundAsset> ms (new dcp::SoundAsset (dcp::Fraction (24, 1), 48000, 1));
ms->set_metadata (mxf_meta);
- shared_ptr<dcp::SoundMXFWriter> sound_writer = ms->start_write ("build/test/DCP/dcp_test2/audio.mxf", dcp::SMPTE);
+ shared_ptr<dcp::SoundAssetWriter> sound_writer = ms->start_write ("build/test/DCP/dcp_test2/audio.mxf", dcp::SMPTE);
SF_INFO info;
info.format = 0;
#include "cpl.h"
#include "decrypted_kdm.h"
#include "encrypted_kdm.h"
-#include "mono_picture_mxf.h"
+#include "mono_picture_asset.h"
#include "reel_picture_asset.h"
#include "reel.h"
#include "test.h"
get_frame (dcp::DCP const & dcp)
{
shared_ptr<const dcp::Reel> reel = dcp.cpls().front()->reels().front ();
- shared_ptr<dcp::PictureMXF> picture = reel->main_picture()->mxf ();
+ shared_ptr<dcp::PictureAsset> picture = reel->main_picture()->asset ();
BOOST_CHECK (picture);
- shared_ptr<const dcp::MonoPictureMXF> mono_picture = dynamic_pointer_cast<const dcp::MonoPictureMXF> (picture);
+ shared_ptr<const dcp::MonoPictureAsset> mono_picture = dynamic_pointer_cast<const dcp::MonoPictureAsset> (picture);
shared_ptr<const dcp::MonoPictureFrame> j2k_frame = mono_picture->get_frame (0);
shared_ptr<dcp::XYZImage> xyz = j2k_frame->xyz_image();
#include "dcp.h"
#include "signer.h"
#include "cpl.h"
-#include "mono_picture_mxf.h"
-#include "picture_mxf_writer.h"
-#include "sound_mxf_writer.h"
-#include "sound_mxf.h"
+#include "mono_picture_asset.h"
+#include "picture_asset_writer.h"
+#include "sound_asset_writer.h"
+#include "sound_asset.h"
#include "reel.h"
#include "test.h"
#include "file.h"
dcp::Key key;
- shared_ptr<dcp::MonoPictureMXF> mp (new dcp::MonoPictureMXF (dcp::Fraction (24, 1)));
+ shared_ptr<dcp::MonoPictureAsset> mp (new dcp::MonoPictureAsset (dcp::Fraction (24, 1)));
mp->set_metadata (mxf_metadata);
mp->set_key (key);
- shared_ptr<dcp::PictureMXFWriter> writer = mp->start_write ("build/test/DCP/encryption_test/video.mxf", dcp::SMPTE, false);
+ shared_ptr<dcp::PictureAssetWriter> writer = mp->start_write ("build/test/DCP/encryption_test/video.mxf", dcp::SMPTE, false);
dcp::File j2c ("test/data/32x32_red_square.j2c");
for (int i = 0; i < 24; ++i) {
writer->write (j2c.data (), j2c.size ());
}
writer->finalize ();
- shared_ptr<dcp::SoundMXF> ms (new dcp::SoundMXF (dcp::Fraction (24, 1), 48000, 1));
+ shared_ptr<dcp::SoundAsset> ms (new dcp::SoundAsset (dcp::Fraction (24, 1), 48000, 1));
ms->set_key (key);
- shared_ptr<dcp::SoundMXFWriter> sound_writer = ms->start_write ("build/test/DCP/encryption_test/audio.mxf", dcp::SMPTE);
+ shared_ptr<dcp::SoundAssetWriter> sound_writer = ms->start_write ("build/test/DCP/encryption_test/audio.mxf", dcp::SMPTE);
SF_INFO info;
info.format = 0;
#include <boost/test/unit_test.hpp>
#include <boost/filesystem.hpp>
-#include "mono_picture_mxf_writer.h"
-#include "mono_picture_mxf.h"
+#include "mono_picture_asset_writer.h"
+#include "mono_picture_asset.h"
#include "KM_util.h"
using std::string;
boost::filesystem::remove_all ("build/test/baz");
boost::filesystem::create_directories ("build/test/baz");
- shared_ptr<dcp::MonoPictureMXF> mp (new dcp::MonoPictureMXF (dcp::Fraction (24, 1)));
- shared_ptr<dcp::PictureMXFWriter> writer = mp->start_write ("build/test/baz/video1.mxf", dcp::SMPTE, false);
+ shared_ptr<dcp::MonoPictureAsset> mp (new dcp::MonoPictureAsset (dcp::Fraction (24, 1)));
+ shared_ptr<dcp::PictureAssetWriter> writer = mp->start_write ("build/test/baz/video1.mxf", dcp::SMPTE, false);
int written_size = 0;
for (int i = 0; i < 24; ++i) {
Kumu::ResetTestRNG ();
#endif
- mp.reset (new dcp::MonoPictureMXF (dcp::Fraction (24, 1)));
+ mp.reset (new dcp::MonoPictureAsset (dcp::Fraction (24, 1)));
writer = mp->start_write ("build/test/baz/video2.mxf", dcp::SMPTE, true);
writer->write (data, size);
#include "decrypted_kdm.h"
#include "encrypted_kdm.h"
#include "signer.h"
-#include "mono_picture_mxf.h"
-#include "sound_mxf.h"
+#include "mono_picture_asset.h"
+#include "sound_asset.h"
#include "reel.h"
#include "test.h"
#include "cpl.h"
#include "mono_picture_frame.h"
#include "certificate_chain.h"
-#include "mono_picture_mxf_writer.h"
+#include "mono_picture_asset_writer.h"
#include "reel_picture_asset.h"
#include "reel_mono_picture_asset.h"
#include "file.h"
using boost::shared_ptr;
using boost::scoped_array;
-/* Build an encrypted picture MXF and a KDM for it and check that the KDM can be decrypted */
+/* Build an encrypted picture asset and a KDM for it and check that the KDM can be decrypted */
BOOST_AUTO_TEST_CASE (round_trip_test)
{
shared_ptr<dcp::Signer> signer (new dcp::Signer ("openssl"));
boost::filesystem::path work_dir = "build/test/round_trip_test";
boost::filesystem::create_directory (work_dir);
- shared_ptr<dcp::MonoPictureMXF> mxf_A (new dcp::MonoPictureMXF (dcp::Fraction (24, 1)));
- shared_ptr<dcp::PictureMXFWriter> writer = mxf_A->start_write (work_dir / "video.mxf", dcp::SMPTE, false);
+ shared_ptr<dcp::MonoPictureAsset> asset_A (new dcp::MonoPictureAsset (dcp::Fraction (24, 1)));
+ shared_ptr<dcp::PictureAssetWriter> writer = asset_A->start_write (work_dir / "video.mxf", dcp::SMPTE, false);
dcp::File j2c ("test/data/32x32_red_square.j2c");
for (int i = 0; i < 24; ++i) {
writer->write (j2c.data (), j2c.size ());
dcp::Key key;
- mxf_A->set_key (key);
+ asset_A->set_key (key);
shared_ptr<dcp::CPL> cpl (new dcp::CPL ("A Test DCP", dcp::FEATURE));
shared_ptr<dcp::Reel> reel (new dcp::Reel ());
- reel->add (shared_ptr<dcp::ReelMonoPictureAsset> (new dcp::ReelMonoPictureAsset (mxf_A, 0)));
+ reel->add (shared_ptr<dcp::ReelMonoPictureAsset> (new dcp::ReelMonoPictureAsset (asset_A, 0)));
cpl->add (reel);
/* A KDM using our certificate chain's leaf key pair */
++j;
}
- /* Reload the picture MXF */
- shared_ptr<dcp::MonoPictureMXF> mxf_B (
- new dcp::MonoPictureMXF (work_dir / "video.mxf")
+ /* Reload the picture asset */
+ shared_ptr<dcp::MonoPictureAsset> asset_B (
+ new dcp::MonoPictureAsset (work_dir / "video.mxf")
);
BOOST_CHECK (!kdm_B.keys().empty ());
- mxf_B->set_key (kdm_B.keys().front().key());
+ asset_B->set_key (kdm_B.keys().front().key());
- shared_ptr<dcp::XYZImage> xyz_A = mxf_A->get_frame(0)->xyz_image ();
- shared_ptr<dcp::XYZImage> xyz_B = mxf_B->get_frame(0)->xyz_image ();
+ shared_ptr<dcp::XYZImage> xyz_A = asset_A->get_frame(0)->xyz_image ();
+ shared_ptr<dcp::XYZImage> xyz_B = asset_B->get_frame(0)->xyz_image ();
scoped_array<uint8_t> frame_A (new uint8_t[xyz_A->size().width * xyz_A->size().height * 4]);
dcp::xyz_to_rgba (xyz_A, dcp::ColourConversion::srgb_to_xyz(), frame_A.get());
<< " -V, --version show libdcp version\n"
<< " -h, --help show this help\n"
<< " -v, --verbose be verbose\n"
- << " -n, --mxf-filenames allow differing MXF filenames\n"
<< " --cpl-annotation-texts allow differing CPL annotation texts\n"
<< " -m, --mean-pixel maximum allowed mean pixel error (default 5)\n"
<< " -s, --std-dev-pixel maximum allowed standard deviation of pixel error (default 5)\n"
{ "version", no_argument, 0, 'V'},
{ "help", no_argument, 0, 'h'},
{ "verbose", no_argument, 0, 'v'},
- { "mxf-filenames", no_argument, 0, 'n'},
{ "mean-pixel", required_argument, 0, 'm'},
{ "std-dev-pixel", required_argument, 0, 's'},
{ "keep-going", no_argument, 0, 'k'},
{ 0, 0, 0, 0 }
};
- int c = getopt_long (argc, argv, "Vhvnm:s:kACD:", long_options, &option_index);
+ int c = getopt_long (argc, argv, "Vhvm:s:kACD:", long_options, &option_index);
if (c == -1) {
break;
case 'v':
verbose = true;
break;
- case 'n':
- options.mxf_filenames_can_differ = true;
- break;
case 'm':
options.max_mean_pixel_error = atof (optarg);
break;
#include "dcp.h"
#include "exceptions.h"
#include "reel.h"
-#include "sound_mxf.h"
-#include "picture_mxf.h"
+#include "sound_asset.h"
+#include "picture_asset.h"
#include "subtitle_asset.h"
#include "reel_picture_asset.h"
#include "reel_sound_asset.h"
static void
main_picture (shared_ptr<Reel> reel)
{
- if (reel->main_picture() && reel->main_picture()->mxf()) {
+ if (reel->main_picture() && reel->main_picture()->asset()) {
cout << " Picture: "
- << reel->main_picture()->mxf()->size().width
+ << reel->main_picture()->asset()->size().width
<< "x"
- << reel->main_picture()->mxf()->size().height << "\n";
+ << reel->main_picture()->asset()->size().height << "\n";
}
}
static void
main_sound (shared_ptr<Reel> reel)
{
- if (reel->main_sound() && reel->main_sound()->mxf()) {
+ if (reel->main_sound() && reel->main_sound()->asset()) {
cout << " Sound: "
- << reel->main_sound()->mxf()->channels()
+ << reel->main_sound()->asset()->channels()
<< " channels at "
- << reel->main_sound()->mxf()->sampling_rate() << "Hz\n";
+ << reel->main_sound()->asset()->sampling_rate() << "Hz\n";
}
}