return shared_ptr<const StereoPictureFrame> (new StereoPictureFrame (path().string(), n));
}
-shared_ptr<MonoPictureAssetWriter>
+shared_ptr<PictureAssetWriter>
MonoPictureAsset::start_write (bool overwrite, MXFMetadata const & metadata)
{
/* XXX: can't we use shared_ptr here? */
}
-shared_ptr<StereoPictureAssetWriter>
+shared_ptr<PictureAssetWriter>
StereoPictureAsset::start_write (bool overwrite, MXFMetadata const & metadata)
{
/* XXX: can't we use shared_ptr here? */
class MonoPictureFrame;
class StereoPictureFrame;
-class MonoPictureAssetWriter;
-class StereoPictureAssetWriter;
+class PictureAssetWriter;
/** @brief An asset made up of JPEG2000 files */
class PictureAsset : public MXFAsset
* @param size Size of video frame images in pixels.
*/
PictureAsset (std::string directory, std::string mxf_name, boost::signals2::signal<void (float)>* progress, int fps, int intrinsic_duration, bool encrypted, Size);
+
+ virtual boost::shared_ptr<PictureAssetWriter> start_write (bool, MXFMetadata const & metadata = MXFMetadata ()) = 0;
bool equals (boost::shared_ptr<const Asset> other, EqualityOptions opt, boost::function<void (NoteType, std::string)> note) const;
MonoPictureAsset (std::string directory, std::string mxf_name, int fps, Size size);
/** Start a progressive write to a MonoPictureAsset */
- boost::shared_ptr<MonoPictureAssetWriter> start_write (bool, MXFMetadata const & metadata = MXFMetadata ());
+ boost::shared_ptr<PictureAssetWriter> start_write (bool, MXFMetadata const & metadata = MXFMetadata ());
boost::shared_ptr<const MonoPictureFrame> get_frame (int n) const;
bool equals (boost::shared_ptr<const Asset> other, EqualityOptions opt, boost::function<void (NoteType, std::string)> note) const;
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<PictureAssetWriter> 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;
}
-PictureAssetWriter::PictureAssetWriter (bool overwrite, MXFMetadata const & metadata)
- : _frames_written (0)
+PictureAssetWriter::PictureAssetWriter (PictureAsset* asset, bool overwrite, MXFMetadata const & metadata)
+ : _asset (asset)
+ , _frames_written (0)
, _started (false)
, _finalized (false)
, _overwrite (overwrite)
}
-struct MonoPictureAssetWriter::ASDCPState
+struct ASDCPStateBase
{
- ASDCPState()
+ ASDCPStateBase ()
: 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
+struct MonoPictureAssetWriter::ASDCPState : public ASDCPStateBase
+{
+ ASDCP::JP2K::MXFWriter mxf_writer;
+};
+
+struct StereoPictureAssetWriter::ASDCPState : public ASDCPStateBase
{
- ASDCPState()
- : frame_buffer (4 * Kumu::Megabyte)
- {}
-
- ASDCP::JP2K::CodestreamParser j2k_parser;
- ASDCP::JP2K::FrameBuffer 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)
+MonoPictureAssetWriter::MonoPictureAssetWriter (PictureAsset* asset, bool overwrite, MXFMetadata const & metadata)
+ : PictureAssetWriter (asset, overwrite, metadata)
, _state (new MonoPictureAssetWriter::ASDCPState)
- , _asset (asset)
{
}
-StereoPictureAssetWriter::StereoPictureAssetWriter (StereoPictureAsset* asset, bool overwrite, MXFMetadata const & metadata)
- : PictureAssetWriter (overwrite, metadata)
+StereoPictureAssetWriter::StereoPictureAssetWriter (PictureAsset* asset, bool overwrite, MXFMetadata const & metadata)
+ : PictureAssetWriter (asset, overwrite, metadata)
, _state (new StereoPictureAssetWriter::ASDCPState)
- , _asset (asset)
+ , _next_eye (EYE_LEFT)
{
}
return FrameInfo (before_offset, _state->mxf_writer.Tell() - before_offset, hash);
}
+/** 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, Eye eye)
+StereoPictureAssetWriter::write (uint8_t* data, int size)
{
assert (!_finalized);
uint64_t const before_offset = _state->mxf_writer.Tell ();
string hash;
- if (ASDCP_FAILURE (_state->mxf_writer.WriteFrame (
- _state->frame_buffer,
- (eye == EYE_LEFT) ? ASDCP::JP2K::SP_LEFT : ASDCP::JP2K::SP_RIGHT,
- 0, 0, &hash)
+ if (ASDCP_FAILURE (
+ _state->mxf_writer.WriteFrame (
+ _state->frame_buffer,
+ _next_eye == EYE_LEFT ? ASDCP::JP2K::SP_LEFT : ASDCP::JP2K::SP_RIGHT,
+ 0,
+ 0,
+ &hash)
)) {
boost::throw_exception (MXFFileError ("error in writing video MXF", _asset->path().string()));
}
+ _next_eye = _next_eye == EYE_LEFT ? EYE_RIGHT : EYE_LEFT;
+
return FrameInfo (before_offset, _state->mxf_writer.Tell() - before_offset, hash);
}
boost::throw_exception (MXFFileError ("error in writing video MXF", _asset->path().string()));
}
+ _next_eye = _next_eye == EYE_LEFT ? EYE_RIGHT : EYE_LEFT;
++_frames_written;
}
namespace libdcp {
-class MonoPictureAsset;
-class StereoPictureAsset;
+class PictureAsset;
struct FrameInfo
{
class PictureAssetWriter : public boost::noncopyable
{
public:
+ virtual FrameInfo write (uint8_t *, int) = 0;
virtual void finalize () = 0;
virtual void fake_write (int) = 0;
template <class P, class Q>
friend void start (PictureAssetWriter *, boost::shared_ptr<P>, Q *, uint8_t *, int);
- PictureAssetWriter (bool, MXFMetadata const &);
+ PictureAssetWriter (PictureAsset *, bool, MXFMetadata const &);
+
+ PictureAsset* _asset;
- /** Number of picture frames written to the asset so far */
+ /** Number of picture frames written to the asset so far. For stereo assets
+ * this will be incremented for each eye (i.e. there will be twice the number
+ * of frames as in a mono asset).
+ */
int _frames_written;
bool _started;
/** true if finalize() has been called */
* 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.
+ * (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.
*/
private:
friend class MonoPictureAsset;
- MonoPictureAssetWriter (MonoPictureAsset *, bool, MXFMetadata const &);
+ MonoPictureAssetWriter (PictureAsset *, bool, MXFMetadata const &);
void start (uint8_t *, int);
/* do this with an opaque pointer so we don't have to include
struct ASDCPState;
boost::shared_ptr<ASDCPState> _state;
-
- MonoPictureAsset* _asset;
};
+/** 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:
- FrameInfo write (uint8_t *, int, Eye);
+ FrameInfo write (uint8_t *, int);
void fake_write (int size);
void finalize ();
private:
friend class StereoPictureAsset;
- StereoPictureAssetWriter (StereoPictureAsset *, bool, MXFMetadata const &);
+ StereoPictureAssetWriter (PictureAsset *, bool, MXFMetadata const &);
void start (uint8_t *, int);
/* do this with an opaque pointer so we don't have to include
struct ASDCPState;
boost::shared_ptr<ASDCPState> _state;
- StereoPictureAsset* _asset;
+ libdcp::Eye _next_eye;
};
}
boost::filesystem::remove_all ("build/test/baz");
boost::filesystem::create_directories ("build/test/baz");
shared_ptr<libdcp::MonoPictureAsset> mp (new libdcp::MonoPictureAsset ("build/test/baz", "video1.mxf", 24, libdcp::Size (32, 32)));
- shared_ptr<libdcp::MonoPictureAssetWriter> writer = mp->start_write (false);
+ shared_ptr<libdcp::PictureAssetWriter> writer = mp->start_write (false);
int written_size = 0;
for (int i = 0; i < 24; ++i) {