Simplify streaming API a bit.
authorCarl Hetherington <cth@carlh.net>
Tue, 23 Jul 2013 13:47:59 +0000 (14:47 +0100)
committerCarl Hetherington <cth@carlh.net>
Tue, 23 Jul 2013 13:47:59 +0000 (14:47 +0100)
src/picture_asset.cc
src/picture_asset.h
src/picture_asset_writer.cc
src/picture_asset_writer.h
test/recovery_test.cc

index c1805e6f3bf124e706faaa672506e2cedab6850f..2aec187ac42657b9cd6b3862b83578162ae3c6e3 100644 (file)
@@ -441,7 +441,7 @@ StereoPictureAsset::get_frame (int n) const
        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? */
@@ -460,7 +460,7 @@ StereoPictureAsset::StereoPictureAsset (string directory, string mxf_name, int f
 
 }
 
-shared_ptr<StereoPictureAssetWriter>
+shared_ptr<PictureAssetWriter>
 StereoPictureAsset::start_write (bool overwrite, MXFMetadata const & metadata)
 {
        /* XXX: can't we use shared_ptr here? */
index 58d9c748a58f63a4bb2dce02195594a481283e8c..f1b14bd6bf7fef2c2e555d78469d81c0e2b1607a 100644 (file)
@@ -34,8 +34,7 @@ namespace libdcp
 
 class MonoPictureFrame;        
 class StereoPictureFrame;
-class MonoPictureAssetWriter;
-class StereoPictureAssetWriter;
+class PictureAssetWriter;
 
 /** @brief An asset made up of JPEG2000 files */
 class PictureAsset : public MXFAsset
@@ -60,6 +59,8 @@ public:
         *  @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;
 
@@ -154,7 +155,7 @@ public:
        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;
@@ -183,7 +184,7 @@ public:
        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;
index 32e13a176312eb9196153a8a8d52d6aa74398594..8ac76c9c522096a4aef61f63a1410ca059f8f4eb 100644 (file)
@@ -41,8 +41,9 @@ FrameInfo::write (ostream& s)
 }
 
 
-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)
@@ -51,47 +52,42 @@ PictureAssetWriter::PictureAssetWriter (bool overwrite, MXFMetadata const & meta
        
 }
 
-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)
 {
 
 }
@@ -158,8 +154,12 @@ MonoPictureAssetWriter::write (uint8_t* data, int size)
        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);
 
@@ -174,15 +174,20 @@ StereoPictureAssetWriter::write (uint8_t* data, int size, Eye eye)
        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);
 }
 
@@ -209,6 +214,7 @@ StereoPictureAssetWriter::fake_write (int size)
                boost::throw_exception (MXFFileError ("error in writing video MXF", _asset->path().string()));
        }
 
+       _next_eye = _next_eye == EYE_LEFT ? EYE_RIGHT : EYE_LEFT;
        ++_frames_written;
 }
 
index 89651902b1fb93e58e4ef85605a375f04665b47a..189ec422a7f15c9d2e2951a5d687e829c2c85e52 100644 (file)
@@ -27,8 +27,7 @@
 
 namespace libdcp {
 
-class MonoPictureAsset;        
-class StereoPictureAsset;      
+class PictureAsset;    
 
 struct FrameInfo
 {
@@ -50,6 +49,7 @@ 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;
        
@@ -57,9 +57,14 @@ protected:
        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 */
@@ -74,7 +79,7 @@ protected:
  *  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.
  */
@@ -88,7 +93,7 @@ public:
 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
@@ -97,21 +102,29 @@ private:
           
        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
@@ -121,7 +134,7 @@ private:
        struct ASDCPState;
        boost::shared_ptr<ASDCPState> _state;
 
-       StereoPictureAsset* _asset;
+       libdcp::Eye _next_eye;
 };
 
 }
index f397b96b4a0c2d7735f474e27f9a4e00fc7b4ebf..df9a839cbe2a3eb90f87032c958e847b0be17a02 100644 (file)
@@ -42,7 +42,7 @@ BOOST_AUTO_TEST_CASE (recovery)
        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) {