Partial subtitle work.
authorCarl Hetherington <cth@carlh.net>
Mon, 13 Aug 2012 00:17:09 +0000 (01:17 +0100)
committerCarl Hetherington <cth@carlh.net>
Mon, 13 Aug 2012 00:17:09 +0000 (01:17 +0100)
src/asset.cc
src/asset.h
src/picture_asset.cc
src/picture_asset.h
src/sound_asset.cc
src/sound_asset.h
src/util.h
src/wscript
src/xml.cc
src/xml.h
test/tests.cc

index d8cf25dae5922f0d973991a2cef918ab1dd3ece8..a7e28fd4b0aa5888ca18a78bff9365654f256c9e 100644 (file)
@@ -34,12 +34,9 @@ using namespace std;
 using namespace boost;
 using namespace libdcp;
 
-Asset::Asset (string directory, string mxf_name, sigc::signal1<void, float>* progress, int fps, int length)
+Asset::Asset (string directory, string file_name)
        : _directory (directory)
-       , _mxf_name (mxf_name)
-       , _progress (progress)
-       , _fps (fps)
-       , _length (length)
+       , _file_name (file_name)
        , _uuid (make_uuid ())
 {
        
@@ -50,9 +47,9 @@ Asset::write_to_pkl (ostream& s) const
 {
        s << "    <Asset>\n"
          << "      <Id>urn:uuid:" << _uuid << "</Id>\n"
-         << "      <AnnotationText>" << _mxf_name << "</AnnotationText>\n"
+         << "      <AnnotationText>" << _file_name << "</AnnotationText>\n"
          << "      <Hash>" << digest() << "</Hash>\n"
-         << "      <Size>" << filesystem::file_size(mxf_path()) << "</Size>\n"
+         << "      <Size>" << filesystem::file_size(path()) << "</Size>\n"
          << "      <Type>application/mxf</Type>\n"
          << "    </Asset>\n";
 }
@@ -64,105 +61,30 @@ Asset::write_to_assetmap (ostream& s) const
          << "      <Id>urn:uuid:" << _uuid << "</Id>\n"
          << "      <ChunkList>\n"
          << "        <Chunk>\n"
-         << "          <Path>" << _mxf_name << "</Path>\n"
+         << "          <Path>" << _file_name << "</Path>\n"
          << "          <VolumeIndex>1</VolumeIndex>\n"
          << "          <Offset>0</Offset>\n"
-         << "          <Length>" << filesystem::file_size(mxf_path()) << "</Length>\n"
+         << "          <Length>" << filesystem::file_size(path()) << "</Length>\n"
          << "        </Chunk>\n"
          << "      </ChunkList>\n"
          << "    </Asset>\n";
 }
 
-void
-Asset::fill_writer_info (ASDCP::WriterInfo* writer_info) const
-{
-       writer_info->ProductVersion = Metadata::instance()->product_version;
-       writer_info->CompanyName = Metadata::instance()->company_name;
-       writer_info->ProductName = Metadata::instance()->product_name.c_str();
-
-       writer_info->LabelSetType = ASDCP::LS_MXF_SMPTE;
-       unsigned int c;
-       Kumu::hex2bin (_uuid.c_str(), writer_info->AssetUUID, Kumu::UUID_Length, &c);
-       assert (c == Kumu::UUID_Length);
-}
-
 filesystem::path
-Asset::mxf_path () const
+Asset::path () const
 {
        filesystem::path p;
        p /= _directory;
-       p /= _mxf_name;
+       p /= _file_name;
        return p;
 }
 
-list<string>
-Asset::equals (shared_ptr<const Asset> other, EqualityOptions opt) const
-{
-       list<string> notes;
-       
-       if (opt.flags & LIBDCP_METADATA) {
-               if (_mxf_name != other->_mxf_name) {
-                       notes.push_back ("MXF names differ");
-               }
-               if (_fps != other->_fps) {
-                       notes.push_back ("MXF frames per second differ");
-               }
-               if (_length != other->_length) {
-                       notes.push_back ("MXF lengths differ");
-               }
-       }
-       
-       if (opt.flags & MXF_BITWISE) {
-
-               if (digest() != other->digest()) {
-                       notes.push_back ("MXF digests differ");
-               }
-               
-               if (filesystem::file_size (mxf_path()) != filesystem::file_size (other->mxf_path())) {
-                       notes.push_back (mxf_path().string() + " and " + other->mxf_path().string() + " sizes differ");
-                       return notes;
-               }
-               
-               ifstream a (mxf_path().string().c_str(), ios::binary);
-               ifstream b (other->mxf_path().string().c_str(), ios::binary);
-
-               int buffer_size = 65536;
-               char abuffer[buffer_size];
-               char bbuffer[buffer_size];
-
-               int n = filesystem::file_size (mxf_path ());
-
-               while (n) {
-                       int const t = min (n, buffer_size);
-                       a.read (abuffer, t);
-                       b.read (bbuffer, t);
-
-                       if (memcmp (abuffer, bbuffer, t) != 0) {
-                               notes.push_back (mxf_path().string() + " and " + other->mxf_path().string() + " content differs");
-                               return notes;
-                       }
-
-                       n -= t;
-               }
-       }
-
-       return notes;
-}
-
 string
 Asset::digest () const
 {
        if (_digest.empty ()) {
-               _digest = make_digest (mxf_path().string(), 0);
+               _digest = make_digest (path().string(), 0);
        }
 
        return _digest;
 }
-
-int
-Asset::length () const
-{
-       return _length;
-}
-
-       
index b7b2065b78447625861fd1867d07b94ab02fdc59..0c8df0c85b6621022b627394e3678125639fd69d 100644 (file)
@@ -44,13 +44,10 @@ class Asset
 {
 public:
        /** Construct an Asset.
-        *  @param directory Directory where MXF file is.
-        *  @param mxf_name Name of MXF file.
-        *  @param progress Signal to inform of progress.
-        *  @param fps Frames per second.
-        *  @param length Length in frames.
+        *  @param directory Directory where our XML or MXF file is.
+        *  @param file_name Name of our file within directory.
         */
-       Asset (std::string directory, std::string mxf_path, sigc::signal1<void, float>* progress, int fps, int length);
+       Asset (std::string directory, std::string file_name);
 
        /** Write details of the asset to a CPL stream.
         *  @param s Stream.
@@ -67,37 +64,24 @@ public:
         */
        void write_to_assetmap (std::ostream& s) const;
 
-       virtual std::list<std::string> equals (boost::shared_ptr<const Asset> other, EqualityOptions opt) const;
-
-       int length () const;
+       virtual std::list<std::string> equals (boost::shared_ptr<const Asset> other, EqualityOptions opt) const = 0;
 
 protected:
        friend class PictureAsset;
        friend class SoundAsset;
        
-       /** Fill in a ADSCP::WriteInfo struct.
-        *  @param w struct to fill in.
-        */
-       void fill_writer_info (ASDCP::WriterInfo* w) const;
-
-       boost::filesystem::path mxf_path () const;
        std::string digest () const;
+       boost::filesystem::path path () const;
 
-       /** Directory that our MXF file is in */
+       /** Directory that our MXF or XML file is in */
        std::string _directory;
-       /** Name of our MXF file */
-       std::string _mxf_name;
-       /** Signal to emit to report progress */
-       sigc::signal1<void, float>* _progress;
-       /** Frames per second */
-       int _fps;
-       /** Length in frames */
-       int _length;
+       /** Name of our MXF or XML file */
+       std::string _file_name;
        /** Our UUID */
        std::string _uuid;
 
 private:       
-       /** Digest of our MXF */
+       /** Digest of our MXF or XML file */
        mutable std::string _digest;
 };
 
index 7b6dd29396a97db3bb936fd51792287b8eda3d87..dd1853a60a23cbc73b5fb1d3c3294afe398242d3 100644 (file)
@@ -49,7 +49,7 @@ PictureAsset::PictureAsset (
        int length,
        int width,
        int height)
-       : Asset (directory, mxf_name, progress, fps, length)
+       : MXFAsset (directory, mxf_name, progress, fps, length)
        , _width (width)
        , _height (height)
 {
@@ -65,7 +65,7 @@ PictureAsset::PictureAsset (
        int length,
        int width,
        int height)
-       : Asset (directory, mxf_name, progress, fps, length)
+       : MXFAsset (directory, mxf_name, progress, fps, length)
        , _width (width)
        , _height (height)
 {
@@ -73,11 +73,11 @@ PictureAsset::PictureAsset (
 }
 
 PictureAsset::PictureAsset (string directory, string mxf_name, int fps, int length)
-       : Asset (directory, mxf_name, 0, fps, length)
+       : MXFAsset (directory, mxf_name, 0, fps, length)
 {
        ASDCP::JP2K::MXFReader reader;
-       if (ASDCP_FAILURE (reader.OpenRead (mxf_path().string().c_str()))) {
-               throw FileError ("could not open MXF file for reading", mxf_path().string());
+       if (ASDCP_FAILURE (reader.OpenRead (path().string().c_str()))) {
+               throw FileError ("could not open MXF file for reading", path().string());
        }
        
        ASDCP::JP2K::PictureDescriptor desc;
@@ -113,8 +113,8 @@ PictureAsset::construct (sigc::slot<string, int> get_path)
        fill_writer_info (&writer_info);
        
        ASDCP::JP2K::MXFWriter mxf_writer;
-       if (ASDCP_FAILURE (mxf_writer.OpenWrite (mxf_path().string().c_str(), writer_info, picture_desc))) {
-               throw FileError ("could not open MXF file for writing", mxf_path().string());
+       if (ASDCP_FAILURE (mxf_writer.OpenWrite (path().string().c_str(), writer_info, picture_desc))) {
+               throw FileError ("could not open MXF file for writing", path().string());
        }
 
        for (int i = 0; i < _length; ++i) {
@@ -143,7 +143,7 @@ PictureAsset::write_to_cpl (ostream& s) const
 {
        s << "        <MainPicture>\n"
          << "          <Id>urn:uuid:" << _uuid << "</Id>\n"
-         << "          <AnnotationText>" << _mxf_name << "</AnnotationText>\n"
+         << "          <AnnotationText>" << _file_name << "</AnnotationText>\n"
          << "          <EditRate>" << _fps << " 1</EditRate>\n"
          << "          <IntrinsicDuration>" << _length << "</IntrinsicDuration>\n"
          << "          <EntryPoint>0</EntryPoint>\n"
@@ -157,17 +157,17 @@ PictureAsset::write_to_cpl (ostream& s) const
 list<string>
 PictureAsset::equals (shared_ptr<const Asset> other, EqualityOptions opt) const
 {
-       list<string> notes = Asset::equals (other, opt);
+       list<string> notes = MXFAsset::equals (other, opt);
                     
        if (opt.flags & MXF_INSPECT) {
                ASDCP::JP2K::MXFReader reader_A;
-               if (ASDCP_FAILURE (reader_A.OpenRead (mxf_path().string().c_str()))) {
-                       throw FileError ("could not open MXF file for reading", mxf_path().string());
+               if (ASDCP_FAILURE (reader_A.OpenRead (path().string().c_str()))) {
+                       throw FileError ("could not open MXF file for reading", path().string());
                }
 
                ASDCP::JP2K::MXFReader reader_B;
-               if (ASDCP_FAILURE (reader_B.OpenRead (other->mxf_path().string().c_str()))) {
-                       throw FileError ("could not open MXF file for reading", mxf_path().string());
+               if (ASDCP_FAILURE (reader_B.OpenRead (other->path().string().c_str()))) {
+                       throw FileError ("could not open MXF file for reading", path().string());
                }
 
                ASDCP::JP2K::PictureDescriptor desc_A;
@@ -319,5 +319,5 @@ PictureAsset::decompress_j2k (uint8_t* data, int64_t size) const
 shared_ptr<const PictureFrame>
 PictureAsset::get_frame (int n) const
 {
-       return shared_ptr<const PictureFrame> (new PictureFrame (mxf_path().string(), n));
+       return shared_ptr<const PictureFrame> (new PictureFrame (path().string(), n));
 }
index c0e5f6498200845b83c0f9f280297d1cba162ed1..f2c4bb34d3adfbc0c9d5c6491f5083672c127e3f 100644 (file)
@@ -22,7 +22,7 @@
  */
 
 #include <openjpeg.h>
-#include "asset.h"
+#include "mxf_asset.h"
 
 namespace libdcp
 {
@@ -30,7 +30,7 @@ namespace libdcp
 class PictureFrame;    
 
 /** @brief An asset made up of JPEG2000 files */
-class PictureAsset : public Asset
+class PictureAsset : public MXFAsset
 {
 public:
        /** Construct a PictureAsset, generating the MXF from the JPEG2000 files.
index 189343bd8a7f38e86e2d00499666296772be8347..7d8a86c82372626c2909afa1407e8bfe39272a68 100644 (file)
@@ -39,7 +39,7 @@ using namespace libdcp;
 SoundAsset::SoundAsset (
        vector<string> const & files, string directory, string mxf_name, sigc::signal1<void, float>* progress, int fps, int length
        )
-       : Asset (directory, mxf_name, progress, fps, length)
+       : MXFAsset (directory, mxf_name, progress, fps, length)
        , _channels (files.size ())
        , _sampling_rate (0)
 {
@@ -49,7 +49,7 @@ SoundAsset::SoundAsset (
 SoundAsset::SoundAsset (
        sigc::slot<string, Channel> get_path, string directory, string mxf_name, sigc::signal1<void, float>* progress, int fps, int length, int channels
        )
-       : Asset (directory, mxf_name, progress, fps, length)
+       : MXFAsset (directory, mxf_name, progress, fps, length)
        , _channels (channels)
        , _sampling_rate (0)
 {
@@ -57,12 +57,12 @@ SoundAsset::SoundAsset (
 }
 
 SoundAsset::SoundAsset (string directory, string mxf_name, int fps, int length)
-       : Asset (directory, mxf_name, 0, fps, length)
+       : MXFAsset (directory, mxf_name, 0, fps, length)
        , _channels (0)
 {
        ASDCP::PCM::MXFReader reader;
-       if (ASDCP_FAILURE (reader.OpenRead (mxf_path().string().c_str()))) {
-               throw FileError ("could not open MXF file for reading", mxf_path().string());
+       if (ASDCP_FAILURE (reader.OpenRead (path().string().c_str()))) {
+               throw FileError ("could not open MXF file for reading", path().string());
        }
 
        
@@ -135,8 +135,8 @@ SoundAsset::construct (sigc::slot<string, Channel> get_path)
        fill_writer_info (&writer_info);
 
        ASDCP::PCM::MXFWriter mxf_writer;
-       if (ASDCP_FAILURE (mxf_writer.OpenWrite (mxf_path().string().c_str(), writer_info, audio_desc))) {
-               throw FileError ("could not open audio MXF for writing", mxf_path().string());
+       if (ASDCP_FAILURE (mxf_writer.OpenWrite (path().string().c_str(), writer_info, audio_desc))) {
+               throw FileError ("could not open audio MXF for writing", path().string());
        }
 
        for (int i = 0; i < _length; ++i) {
@@ -183,7 +183,7 @@ SoundAsset::write_to_cpl (ostream& s) const
 {
        s << "        <MainSound>\n"
          << "          <Id>urn:uuid:" << _uuid << "</Id>\n"
-         << "          <AnnotationText>" << _mxf_name << "</AnnotationText>\n"
+         << "          <AnnotationText>" << _file_name << "</AnnotationText>\n"
          << "          <EditRate>" << _fps << " 1</EditRate>\n"
          << "          <IntrinsicDuration>" << _length << "</IntrinsicDuration>\n"
          << "          <EntryPoint>0</EntryPoint>\n"
@@ -194,19 +194,19 @@ SoundAsset::write_to_cpl (ostream& s) const
 list<string>
 SoundAsset::equals (shared_ptr<const Asset> other, EqualityOptions opt) const
 {
-       list<string> notes = Asset::equals (other, opt);
+       list<string> notes = MXFAsset::equals (other, opt);
                     
        if (opt.flags & MXF_INSPECT) {
                ASDCP::PCM::MXFReader reader_A;
-               if (ASDCP_FAILURE (reader_A.OpenRead (mxf_path().string().c_str()))) {
-                       cout << "failed " << mxf_path() << "\n";
-                       throw FileError ("could not open MXF file for reading", mxf_path().string());
+               if (ASDCP_FAILURE (reader_A.OpenRead (path().string().c_str()))) {
+                       cout << "failed " << path() << "\n";
+                       throw FileError ("could not open MXF file for reading", path().string());
                }
 
                ASDCP::PCM::MXFReader reader_B;
-               if (ASDCP_FAILURE (reader_B.OpenRead (other->mxf_path().string().c_str()))) {
-                       cout << "failed " << other->mxf_path() << "\n";
-                       throw FileError ("could not open MXF file for reading", mxf_path().string());
+               if (ASDCP_FAILURE (reader_B.OpenRead (other->path().string().c_str()))) {
+                       cout << "failed " << other->path() << "\n";
+                       throw FileError ("could not open MXF file for reading", path().string());
                }
 
                ASDCP::PCM::AudioDescriptor desc_A;
@@ -264,5 +264,5 @@ SoundAsset::equals (shared_ptr<const Asset> other, EqualityOptions opt) const
 shared_ptr<const SoundFrame>
 SoundAsset::get_frame (int n) const
 {
-       return shared_ptr<const SoundFrame> (new SoundFrame (mxf_path().string(), n));
+       return shared_ptr<const SoundFrame> (new SoundFrame (path().string(), n));
 }
index a0dd0a6e411b2de5771413164dcd31eb09aa8bc4..06edfc335d42ac52f0dd14307d0a3f7f7fbcb77d 100644 (file)
@@ -24,7 +24,7 @@
  *  @brief An asset made up of WAV files
  */
 
-#include "asset.h"
+#include "mxf_asset.h"
 #include "types.h"
 
 namespace libdcp
@@ -33,7 +33,7 @@ namespace libdcp
 class SoundFrame;      
 
 /** @brief An asset made up of WAV files */
-class SoundAsset : public Asset
+class SoundAsset : public MXFAsset
 {
 public:
        /** Construct a SoundAsset, generating the MXF from the WAV files.
index ac13e9f6120e88b69019428666e88816bb9f54e0..3bbcbabb0057c998c1a85f652393b114698dfdf2 100644 (file)
@@ -43,5 +43,5 @@ extern std::string make_digest (std::string filename, sigc::signal1<void, float>
 extern std::string content_kind_to_string (ContentKind kind);
 extern ContentKind content_kind_from_string (std::string kind);
 extern bool ends_with (std::string big, std::string little);
-       
+
 }
index 0a0c3e66fc68bc2fed5b80ae0a96565b411a4cdf..fd0590c1b7c4ba0800cbb39b56d8d62f75a4e417 100644 (file)
@@ -10,7 +10,10 @@ def build(bld):
                  asset_map.cc
                  cpl.cc
                  dcp.cc        
+                 dcp_time.cc
+                 mxf_asset.cc
                  sound_asset.cc
+                 subtitle_asset.cc
                  picture_asset.cc
                  picture_frame.cc
                  pkl.cc
index 206cb5f0486ac845039366b2c4ec25f627aea2c1..79baa01cda1b5a5309c4a1a47de1b74ecc88153e 100644 (file)
@@ -139,6 +139,12 @@ XMLNode::ignore_node (string name)
        _taken.push_back (name);
 }
 
+Time
+XMLNode::time_attribute (string name)
+{
+
+}
+
 void
 XMLNode::done ()
 {
index e5667b8f10a16db269e128dabe75a763f304ab91..5c0719580e2e1c3af58a97dcee200a06abee3664 100644 (file)
--- a/src/xml.h
+++ b/src/xml.h
@@ -33,6 +33,9 @@ protected:
        void ignore_node (std::string);
        void done ();
 
+       Time time_attribute (std::string);
+       float float_attribute (std::string);
+
        template <class T>
        boost::shared_ptr<T> sub_node (std::string name) {
                return boost::shared_ptr<T> (new T (xml_node (name)));
@@ -51,9 +54,8 @@ protected:
        }
        
        template <class T>
-       std::list<boost::shared_ptr<T> > sub_nodes (std::string name, std::string sub) {
-               XMLNode p (xml_node (name));
-               std::list<xmlpp::Node*> n = p.xml_nodes (sub);
+       std::list<boost::shared_ptr<T> > sub_nodes (std::string name) {
+               std::list<xmlpp::Node*> n = xml_nodes (name);
                std::list<boost::shared_ptr<T> > r;
                for (typename std::list<xmlpp::Node*>::iterator i = n.begin(); i != n.end(); ++i) {
                        r.push_back (boost::shared_ptr<T> (new T (*i)));
@@ -61,6 +63,12 @@ protected:
                return r;
        }
 
+       template <class T>
+       std::list<boost::shared_ptr<T> > sub_nodes (std::string name, std::string sub) {
+               XMLNode p (xml_node (name));
+               return p.sub_nodes<T> (sub);
+       }
+
        xmlpp::Node const * _node;
 
 private:
index 39528c6257f2f7a86b690bda127424b8d3f5e580..c6d286221227ea3b10f9014987b9fd2ce93cb715 100644 (file)
@@ -24,6 +24,7 @@
 #include "metadata.h"
 #include "types.h"
 #include "exceptions.h"
+#include "subtitle_asset.h"
 
 #define BOOST_TEST_DYN_LINK
 #define BOOST_TEST_MODULE libdcp_test
@@ -85,4 +86,21 @@ BOOST_AUTO_TEST_CASE (read_dcp)
        BOOST_CHECK_EQUAL (d.length(), 24);
 }
        
+BOOST_AUTO_TEST_CASE (subtitles)
+{
+       libdcp::SubtitleAsset subs ("test/ref", "subs.xml");
+
+       BOOST_CHECK_EQUAL (subs.language(), "French");
+       BOOST_CHECK_EQUAL (subs.fonts().size(), 1);
+       BOOST_CHECK_EQUAL (subs.fonts().front()->subtitles().size(), 4);
+
+       list<shared_ptr<libdcp::Subtitle> >::const_iterator i = subs.fonts().front()->subtitles().begin ();
+
+       BOOST_CHECK_EQUAL ((*i)->in(), libdcp::Time (0, 0, 5, 198));
+       BOOST_CHECK_EQUAL ((*i)->out(), libdcp::Time (0, 0, 7, 115));
+       BOOST_CHECK_EQUAL ((*i)->texts().size(), 1);
+       BOOST_CHECK_EQUAL ((*i)->texts().front()->v_position(), 15);
+       BOOST_CHECK_EQUAL ((*i)->texts().front()->text(), "My jacket was Idi Amin's");
+}
+