diff options
| author | Carl Hetherington <cth@carlh.net> | 2013-07-22 08:22:52 +0100 |
|---|---|---|
| committer | Carl Hetherington <cth@carlh.net> | 2013-07-22 08:22:52 +0100 |
| commit | bfbd64d680a0cbe9867b23088023ae5f9ecc219b (patch) | |
| tree | 2738025017a12920cfe80ac7b0f37c29e634f55e /src | |
| parent | 6e3bff35a4d9b829eb8e481216a748cd4505ba6c (diff) | |
Some hacks.
Diffstat (limited to 'src')
| -rw-r--r-- | src/picture_asset.cc | 123 | ||||
| -rw-r--r-- | src/picture_asset.h | 79 | ||||
| -rw-r--r-- | src/picture_asset_writer.cc | 225 | ||||
| -rw-r--r-- | src/picture_asset_writer.h | 126 | ||||
| -rw-r--r-- | src/wscript | 1 |
5 files changed, 375 insertions, 179 deletions
diff --git a/src/picture_asset.cc b/src/picture_asset.cc index 824ebf80..2ecfa229 100644 --- a/src/picture_asset.cc +++ b/src/picture_asset.cc @@ -37,6 +37,7 @@ #include "exceptions.h" #include "picture_frame.h" #include "xyz_frame.h" +#include "picture_asset_writer.h" using std::string; using std::ostream; @@ -429,126 +430,14 @@ MonoPictureAsset::start_write (bool overwrite, MXFMetadata const & metadata) return shared_ptr<MonoPictureAssetWriter> (new MonoPictureAssetWriter (this, overwrite, metadata)); } -FrameInfo::FrameInfo (istream& s) -{ - s >> offset >> size >> hash; -} - -void -FrameInfo::write (ostream& s) -{ - s << offset << " " << size << " " << hash; -} - -struct MonoPictureAssetWriter::ASDCPState -{ - ASDCPState() - : frame_buffer (4 * Kumu::Megabyte) - {} - - ASDCP::JP2K::CodestreamParser j2k_parser; - ASDCP::JP2K::FrameBuffer frame_buffer; - ASDCP::JP2K::MXFWriter mxf_writer; - ASDCP::WriterInfo writer_info; - ASDCP::JP2K::PictureDescriptor picture_descriptor; -}; - - -/** @param a Asset to write to. `a' must not be deleted while - * this writer class still exists, or bad things will happen. - */ -MonoPictureAssetWriter::MonoPictureAssetWriter (MonoPictureAsset* a, bool overwrite, MXFMetadata const & m) - : _state (new MonoPictureAssetWriter::ASDCPState) - , _asset (a) - , _frames_written (0) - , _started (false) - , _finalized (false) - , _overwrite (overwrite) - , _metadata (m) -{ - -} - - -void -MonoPictureAssetWriter::start (uint8_t* data, int size) -{ - 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 (_asset->edit_rate(), 1); - - _asset->fill_writer_info (&_state->writer_info, _asset->uuid(), _metadata); - - if (ASDCP_FAILURE (_state->mxf_writer.OpenWrite ( - _asset->path().string().c_str(), - _state->writer_info, - _state->picture_descriptor, - 16384, - _overwrite) - )) { - - boost::throw_exception (MXFFileError ("could not open MXF file for writing", _asset->path().string())); - } - - _started = true; -} - -FrameInfo -MonoPictureAssetWriter::write (uint8_t* data, int size) -{ - 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; - if (ASDCP_FAILURE (_state->mxf_writer.WriteFrame (_state->frame_buffer, 0, 0, &hash))) { - boost::throw_exception (MXFFileError ("error in writing video MXF", _asset->path().string())); - } - - ++_frames_written; - return FrameInfo (before_offset, _state->mxf_writer.Tell() - before_offset, hash); -} - -void -MonoPictureAssetWriter::fake_write (int size) +string +PictureAsset::key_type () const { - assert (_started); - assert (!_finalized); - - if (ASDCP_FAILURE (_state->mxf_writer.FakeWriteFrame (size))) { - boost::throw_exception (MXFFileError ("error in writing video MXF", _asset->path().string())); - } - - ++_frames_written; + return "MDIK"; } -void -MonoPictureAssetWriter::finalize () +StereoPictureAsset::StereoPictureAsset (string directory, string mxf_name, int fps, Size size) + : PictureAsset (directory, mxf_name, 0, fps, 0, false, size) { - assert (!_finalized); - - if (ASDCP_FAILURE (_state->mxf_writer.Finalize())) { - boost::throw_exception (MXFFileError ("error in finalizing video MXF", _asset->path().string())); - } - - _finalized = true; - _asset->set_intrinsic_duration (_frames_written); - _asset->set_duration (_frames_written); -} -string -PictureAsset::key_type () const -{ - return "MDIK"; } diff --git a/src/picture_asset.h b/src/picture_asset.h index cc99ddbc..2031a9ed 100644 --- a/src/picture_asset.h +++ b/src/picture_asset.h @@ -33,7 +33,9 @@ namespace libdcp { class MonoPictureFrame; -class StereoPictureFrame; +class StereoPictureFrame; +class MonoPictureAssetWriter; +class StereoPictureAssetWriter; /** @brief An asset made up of JPEG2000 files */ class PictureAsset : public MXFAsset @@ -84,66 +86,6 @@ private: class MonoPictureAsset; -struct FrameInfo -{ - FrameInfo (uint64_t o, uint64_t s, std::string h) - : offset (o) - , size (s) - , hash (h) - {} - - FrameInfo (std::istream& s); - - void write (std::ostream& s); - - uint64_t offset; - uint64_t size; - std::string hash; -}; - -/** A helper class for writing to MonoPictureAssets 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 MonoPictureAsset::start_write(). - * - * Frames can be written to the MonoPictureAsset by calling write() with a JPEG2000 image - * (a verbatim .j2 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: - FrameInfo write (uint8_t* data, int size); - void fake_write (int size); - void finalize (); - -private: - friend class MonoPictureAsset; - - MonoPictureAssetWriter (MonoPictureAsset *, bool, MXFMetadata const &); - void start (uint8_t *, int); - - /* no copy construction */ - MonoPictureAssetWriter (MonoPictureAssetWriter const &); - MonoPictureAssetWriter& operator= (MonoPictureAssetWriter const &); - - /* do this with an opaque pointer so we don't have to include - ASDCP headers - */ - - struct ASDCPState; - boost::shared_ptr<ASDCPState> _state; - - MonoPictureAsset* _asset; - /** Number of picture frames written to the asset so far */ - int _frames_written; - bool _started; - /** true if finalize() has been called */ - bool _finalized; - bool _overwrite; - MXFMetadata _metadata; -}; /** A 2D (monoscopic) picture asset */ class MonoPictureAsset : public PictureAsset @@ -229,7 +171,20 @@ class StereoPictureAsset : public PictureAsset { public: StereoPictureAsset (std::string directory, std::string mxf_name, int fps, int intrinsic_duration); - + + /** Construct a StereoPictureAsset for progressive writing using + * start_write() and a StereoPictureAssetWriter. + * + * @param directory Directory to put the MXF in. + * @param mxf_name Filename of the MXF within this directory. + * @param fps Video frames per second. + * @param size Size in pixels that the picture frames will be. + */ + StereoPictureAsset (std::string directory, std::string mxf_name, int fps, Size size); + + /** Start a progressive write to a StereoPictureAsset */ + boost::shared_ptr<StereoPictureAssetWriter> start_write (bool, MXFMetadata const & metadata = MXFMetadata ()); + boost::shared_ptr<const StereoPictureFrame> get_frame (int n) const; bool equals (boost::shared_ptr<const Asset> other, EqualityOptions opt, boost::function<void (NoteType, std::string)> note) const; }; diff --git a/src/picture_asset_writer.cc b/src/picture_asset_writer.cc new file mode 100644 index 00000000..748de2db --- /dev/null +++ b/src/picture_asset_writer.cc @@ -0,0 +1,225 @@ +/* + Copyright (C) 2012-2013 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 "KM_fileio.h" +#include "picture_asset_writer.h" +#include "exceptions.h" +#include "picture_asset.h" + +using std::istream; +using std::ostream; +using std::string; +using boost::shared_ptr; +using namespace libdcp; + +FrameInfo::FrameInfo (istream& s) +{ + s >> offset >> size >> hash; +} + +void +FrameInfo::write (ostream& s) +{ + s << offset << " " << size << " " << hash; +} + + +PictureAssetWriter::PictureAssetWriter (bool overwrite, MXFMetadata const & metadata) + : _frames_written (0) + , _started (false) + , _finalized (false) + , _overwrite (overwrite) + , _metadata (metadata) +{ + +} + +struct MonoPictureAssetWriter::ASDCPState +{ + ASDCPState() + : frame_buffer (4 * Kumu::Megabyte) + {} + + ASDCP::JP2K::CodestreamParser j2k_parser; + ASDCP::JP2K::FrameBuffer frame_buffer; + ASDCP::JP2K::MXFWriter mxf_writer; + ASDCP::WriterInfo writer_info; + ASDCP::JP2K::PictureDescriptor picture_descriptor; +}; + +struct StereoPictureAssetWriter::ASDCPState +{ + ASDCPState() + : frame_buffer (4 * Kumu::Megabyte) + {} + + ASDCP::JP2K::CodestreamParser j2k_parser; + ASDCP::JP2K::SFrameBuffer frame_buffer; + ASDCP::JP2K::MXFSWriter mxf_writer; + ASDCP::WriterInfo writer_info; + ASDCP::JP2K::PictureDescriptor picture_descriptor; +}; + +/** @param a Asset to write to. `a' must not be deleted while + * this writer class still exists, or bad things will happen. + */ +MonoPictureAssetWriter::MonoPictureAssetWriter (MonoPictureAsset* asset, bool overwrite, MXFMetadata const & metadata) + : PictureAssetWriter (overwrite, metadata) + , _state (new MonoPictureAssetWriter::ASDCPState) + , _asset (asset) +{ + +} + +StereoPictureAssetWriter::StereoPictureAssetWriter (StereoPictureAsset* asset, bool overwrite, MXFMetadata const & metadata) + : PictureAssetWriter (overwrite, metadata) + , _state (new StereoPictureAssetWriter::ASDCPState) + , _asset (asset) +{ + +} + +template <class P, class Q> +void start (PictureAssetWriter* writer, shared_ptr<P> state, Q* asset, uint8_t* data, int size) +{ + 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 (asset->edit_rate(), 1); + + asset->fill_writer_info (&state->writer_info, asset->uuid(), writer->_metadata); + + if (ASDCP_FAILURE (state->mxf_writer.OpenWrite ( + asset->path().string().c_str(), + state->writer_info, + state->picture_descriptor, + 16384, + writer->_overwrite) + )) { + + boost::throw_exception (MXFFileError ("could not open MXF file for writing", asset->path().string())); + } + + writer->_started = true; +} + +void +MonoPictureAssetWriter::start (uint8_t* data, int size) +{ + ::start (this, _state, _asset, data, size); +} + +void +StereoPictureAssetWriter::start (uint8_t* data, int size) +{ + ::start (this, _state, _asset, data, size); +} + +template <class P, class Q> +FrameInfo write (PictureAssetWriter* writer, shared_ptr<P> state, Q* asset, uint8_t* data, int size) +{ + assert (!writer->_finalized); + + if (!writer->_started) { + writer->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; + if (ASDCP_FAILURE (state->mxf_writer.WriteFrame (state->frame_buffer, 0, 0, &hash))) { + boost::throw_exception (MXFFileError ("error in writing video MXF", asset->path().string())); + } + + ++asset->_frames_written; + return FrameInfo (before_offset, state->mxf_writer.Tell() - before_offset, hash); +} + +FrameInfo +MonoPictureAssetWriter::write (uint8_t* data, int size) +{ + return ::write (this, _state, _asset, data, size); +} + +FrameInfo +StereoPictureAssetWriter::write (uint8_t* data, int size) +{ + return ::write (this, _state, _asset, data, size); +} + +void +MonoPictureAssetWriter::fake_write (int size) +{ + assert (_started); + assert (!_finalized); + + if (ASDCP_FAILURE (_state->mxf_writer.FakeWriteFrame (size))) { + boost::throw_exception (MXFFileError ("error in writing video MXF", _asset->path().string())); + } + + ++_frames_written; +} + +void +StereoPictureAssetWriter::fake_write (int size) +{ + assert (_started); + assert (!_finalized); + + if (ASDCP_FAILURE (_state->mxf_writer.FakeWriteFrame (size))) { + boost::throw_exception (MXFFileError ("error in writing video MXF", _asset->path().string())); + } + + ++_frames_written; +} + +void +MonoPictureAssetWriter::finalize () +{ + assert (!_finalized); + + if (ASDCP_FAILURE (_state->mxf_writer.Finalize())) { + boost::throw_exception (MXFFileError ("error in finalizing video MXF", _asset->path().string())); + } + + _finalized = true; + _asset->set_intrinsic_duration (_frames_written); + _asset->set_duration (_frames_written); +} + +void +StereoPictureAssetWriter::finalize () +{ + assert (!_finalized); + + if (ASDCP_FAILURE (_state->mxf_writer.Finalize())) { + boost::throw_exception (MXFFileError ("error in finalizing video MXF", _asset->path().string())); + } + + _finalized = true; + _asset->set_intrinsic_duration (_frames_written); + _asset->set_duration (_frames_written); +} diff --git a/src/picture_asset_writer.h b/src/picture_asset_writer.h new file mode 100644 index 00000000..5c2b0fef --- /dev/null +++ b/src/picture_asset_writer.h @@ -0,0 +1,126 @@ +/* + Copyright (C) 2012-2013 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 <stdint.h> +#include <string> +#include <fstream> +#include <boost/shared_ptr.hpp> +#include <boost/utility.hpp> +#include "metadata.h" + +namespace libdcp { + +class MonoPictureAsset; +class StereoPictureAsset; + +struct FrameInfo +{ + FrameInfo (uint64_t o, uint64_t s, std::string h) + : offset (o) + , size (s) + , hash (h) + {} + + FrameInfo (std::istream& s); + + void write (std::ostream& s); + + uint64_t offset; + uint64_t size; + std::string hash; +}; + +class PictureAssetWriter : public boost::noncopyable +{ +public: + virtual FrameInfo write (uint8_t *, int) = 0; + virtual void fake_write (int) = 0; + virtual void finalize () = 0; + +protected: + + PictureAssetWriter (bool, MXFMetadata const &); + virtual void start (uint8_t *, int) = 0; + + /** Number of picture frames written to the asset so far */ + int _frames_written; + bool _started; + /** true if finalize() has been called */ + bool _finalized; + bool _overwrite; + MXFMetadata _metadata; +}; + +/** A helper class for writing to MonoPictureAssets 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 MonoPictureAsset::start_write(). + * + * Frames can be written to the MonoPictureAsset by calling write() with a JPEG2000 image + * (a verbatim .j2 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* data, int size); + void fake_write (int size); + void finalize (); + +private: + friend class MonoPictureAsset; + + MonoPictureAssetWriter (MonoPictureAsset *, bool, MXFMetadata const &); + 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; + + MonoPictureAsset* _asset; +}; + +class StereoPictureAssetWriter : public PictureAssetWriter +{ +public: + FrameInfo write (uint8_t* data, int size); + void fake_write (int size); + void finalize (); + +private: + friend class StereoPictureAsset; + + StereoPictureAssetWriter (StereoPictureAsset *, bool, MXFMetadata const &); + 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; + + StereoPictureAsset* _asset; +}; + +} diff --git a/src/wscript b/src/wscript index 16b92447..2f20721c 100644 --- a/src/wscript +++ b/src/wscript @@ -24,6 +24,7 @@ def build(bld): metadata.cc mxf_asset.cc picture_asset.cc + picture_asset_writer.cc picture_frame.cc rec709_linearised_gamma_lut.cc reel.cc |
