Allow functor to obtain content paths.
authorCarl Hetherington <cth@carlh.net>
Tue, 17 Jul 2012 23:23:28 +0000 (00:23 +0100)
committerCarl Hetherington <cth@carlh.net>
Tue, 17 Jul 2012 23:23:28 +0000 (00:23 +0100)
src/dcp.cc
src/dcp.h
src/picture_asset.cc
src/picture_asset.h
src/sound_asset.cc
src/sound_asset.h
src/types.h [new file with mode: 0644]
src/wscript
test/tests.cc

index ca2a2d143e933fb188957f4e7b8f0a8967dfe5bb..c466396cf5313c50e72c926d73628950bc24a9a1 100644 (file)
@@ -44,7 +44,7 @@ DCP::DCP (string directory, string name, ContentType content_type, int fps, int
 }
 
 void
-DCP::add_sound_asset (list<string> const & files)
+DCP::add_sound_asset (vector<string> const & files)
 {
        filesystem::path p;
        p /= _directory;
@@ -53,12 +53,30 @@ DCP::add_sound_asset (list<string> const & files)
 }
 
 void
-DCP::add_picture_asset (list<string> const & files, int w, int h)
+DCP::add_sound_asset (sigc::slot<string, Channel> get_path, int channels)
+{
+       filesystem::path p;
+       p /= _directory;
+       p /= "audio.mxf";
+       _assets.push_back (shared_ptr<SoundAsset> (new SoundAsset (get_path, p.string(), &Progress, _fps, _length, channels)));
+}
+
+void
+DCP::add_picture_asset (vector<string> const & files, int width, int height)
+{
+       filesystem::path p;
+       p /= _directory;
+       p /= "video.mxf";
+       _assets.push_back (shared_ptr<PictureAsset> (new PictureAsset (files, p.string(), &Progress, _fps, _length, width, height)));
+}
+
+void
+DCP::add_picture_asset (sigc::slot<string, int> get_path, int width, int height)
 {
        filesystem::path p;
        p /= _directory;
        p /= "video.mxf";
-       _assets.push_back (shared_ptr<PictureAsset> (new PictureAsset (files, p.string(), &Progress, _fps, _length, w, h)));
+       _assets.push_back (shared_ptr<PictureAsset> (new PictureAsset (get_path, p.string(), &Progress, _fps, _length, width, height)));
 }
 
 void
index b2d20c699d6d5548a75d8958dff7f51abba7c4d4..f683c419b721d57171a4084af5b6cbb252f2073d 100644 (file)
--- a/src/dcp.h
+++ b/src/dcp.h
@@ -24,6 +24,7 @@
 #include <list>
 #include <boost/shared_ptr.hpp>
 #include <sigc++/sigc++.h>
+#include "types.h"
 
 /** @brief Namespace for everything in libdcp */
 namespace libdcp
@@ -41,7 +42,7 @@ class Asset;
  *
  *  libdcp::DCP dcp ("My Film DCP", "My Film", libdcp::DCP::FEATURE, 24, 50000);
  *
- *  list<string> j2k_files;
+ *  vector<string> j2k_files;
  *  j2k_files.push_back ("1.j2c");
  *  ...
  *  j2k_files.push_back ("50000.j2c");
@@ -49,7 +50,7 @@ class Asset;
  *  // These images are 1998x1080 pixels (DCI Flat)
  *  dcp.add_picture_asset (j2k_files, 1998, 1080);
  *
- *  list<string> wav_files;
+ *  vector<string> wav_files;
  *  wav_files.push_back ("L.wav");
  *  wav_files.push_back ("R.wav");
  *  wav_files.push_back ("C.wav");
@@ -101,16 +102,30 @@ public:
 
        /** Add a sound asset.
         *  @param files Pathnames of WAV files to use in the order Left, Right,
-        *  Centre, Lfe (sub), Left surround, Right surround.
+        *  Centre, Lfe (sub), Left surround, Right surround; not all files need
+        *  to be present.
         */
-       void add_sound_asset (std::list<std::string> const & files);
+       void add_sound_asset (std::vector<std::string> const & files);
+
+       /** Add a sound asset.
+        *  @param get_path Functor to get the path to the WAV for a given channel.
+        *  @param channels Number of channels.
+        */
+       void add_sound_asset (sigc::slot<std::string, Channel> get_path, int channels);
 
        /** Add a picture asset.
         *  @param files Pathnames of JPEG2000 files, in frame order.
         *  @param width Width of images in pixels.
         *  @param height Height of images in pixels.
         */
-       void add_picture_asset (std::list<std::string> const & files, int width, int height);
+       void add_picture_asset (std::vector<std::string> const & files, int width, int height);
+
+       /** Add a picture asset.
+        *  @param get_path Functor to get path to the JPEG2000 for a given frame.
+        *  @param width Width of images in pixels.
+        *  @param height Height of images in pixels.
+        */
+       void add_picture_asset (sigc::slot<std::string, int> get_path, int width, int height);
 
        /** Write the required XML files to the directory that was
         *  passed into the constructor.
index 3888ca723faa7dc19fdee8687620821541e55dd5..383d218a6440f9799885bef088f902c3ee44c9df 100644 (file)
@@ -36,7 +36,7 @@ using namespace boost;
 using namespace libdcp;
 
 PictureAsset::PictureAsset (
-       list<string> const & files,
+       sigc::slot<string, int> get_path,
        string mxf_path,
        sigc::signal1<void, float>* progress,
        int fps,
@@ -46,12 +46,39 @@ PictureAsset::PictureAsset (
        : Asset (mxf_path, progress, fps, length)
        , _width (width)
        , _height (height)
+{
+       construct (get_path);
+}
+
+PictureAsset::PictureAsset (
+       vector<string> const & files,
+       string mxf_path,
+       sigc::signal1<void, float>* progress,
+       int fps,
+       int length,
+       int width,
+       int height)
+       : Asset (mxf_path, progress, fps, length)
+       , _width (width)
+       , _height (height)
+{
+       construct (sigc::bind (sigc::mem_fun (*this, &PictureAsset::path_from_list), files));
+}
+
+string
+PictureAsset::path_from_list (int f, vector<string> const & files) const
+{
+       return files[f];
+}
+
+void
+PictureAsset::construct (sigc::slot<string, int> get_path)
 {
        ASDCP::JP2K::CodestreamParser j2k_parser;
        ASDCP::JP2K::FrameBuffer frame_buffer (4 * Kumu::Megabyte);
-       if (ASDCP_FAILURE (j2k_parser.OpenReadFrame (files.front().c_str(), frame_buffer))) {
+       if (ASDCP_FAILURE (j2k_parser.OpenReadFrame (get_path(0).c_str(), frame_buffer))) {
                stringstream s;
-               s << "could not open " << files.front() << " for reading";
+               s << "could not open " << get_path(0) << " for reading";
                throw runtime_error (s.str());
        }
        
@@ -67,11 +94,13 @@ PictureAsset::PictureAsset (
                throw runtime_error ("could not open MXF for writing");
        }
 
-       int j = 0;
-       for (list<string>::const_iterator i = files.begin(); i != files.end(); ++i) {
-               if (ASDCP_FAILURE (j2k_parser.OpenReadFrame (i->c_str(), frame_buffer))) {
+       for (int i = 0; i < _length; ++i) {
+
+               string const path = get_path (i);
+               
+               if (ASDCP_FAILURE (j2k_parser.OpenReadFrame (path.c_str(), frame_buffer))) {
                        stringstream s;
-                       s << "could not open " << *i << " for reading";
+                       s << "could not open " << path << " for reading";
                        throw runtime_error (s.str());
                }
 
@@ -80,8 +109,7 @@ PictureAsset::PictureAsset (
                        throw runtime_error ("error in writing video MXF");
                }
                
-               ++j;
-               (*_progress) (0.5 * float (j) / files.size ());
+               (*_progress) (0.5 * float (i) / _length);
        }
        
        if (ASDCP_FAILURE (mxf_writer.Finalize())) {
index 2f3c7cdf0aa19fe7f34018e9ea2236820bed5095..58dd1dfd216d17700b723fd98abff5b3983f6b3c 100644 (file)
@@ -41,7 +41,7 @@ public:
         *  @param height Height of images in pixels.
         */
        PictureAsset (
-               std::list<std::string> const & files,
+               std::vector<std::string> const & files,
                std::string mxf_path,
                sigc::signal1<void, float>* progress,
                int fps,
@@ -50,12 +50,35 @@ public:
                int height
                );
 
+       /** Construct a PictureAsset, generating the MXF from the JPEG2000 files.
+        *  This may take some time; progress is indicated by emission of the Progress signal.
+        *  @param files Pathnames of JPEG2000 files, in frame order.
+        *  @param mxf_path Pathname of MXF file to create.
+        *  @param progress Signal to inform of progress.
+        *  @param fps Frames per second.
+        *  @param length Length in frames.
+        *  @param width Width of images in pixels.
+        *  @param height Height of images in pixels.
+        */
+       PictureAsset (
+               sigc::slot<std::string, int> get_path,
+               std::string mxf_path,
+               sigc::signal1<void, float>* progress,
+               int fps,
+               int length,
+               int width,
+               int height
+               );
+       
        /** Write details of this asset to a CPL stream.
         *  @param s Stream.
         */
        void write_to_cpl (std::ostream& s) const;
 
 private:
+       std::string path_from_list (int f, std::vector<std::string> const & files) const;
+       void construct (sigc::slot<std::string, int>);
+       
        /** picture width in pixels */
        int _width;
        /** picture height in pixels */
index 8c85f9dfcac5632984c5a6a9bcff2128a56b3a53..0d32db2ab2f833a39eca9a4d8b3a5a344f2e0506 100644 (file)
@@ -32,13 +32,39 @@ using namespace std;
 using namespace boost;
 using namespace libdcp;
 
-SoundAsset::SoundAsset (list<string> const & files, string mxf_path, sigc::signal1<void, float>* progress, int fps, int length)
+SoundAsset::SoundAsset (
+       vector<string> const & files, string mxf_path, sigc::signal1<void, float>* progress, int fps, int length
+       )
        : Asset (mxf_path, progress, fps, length)
+       , _channels (files.size ())
+{
+       construct (sigc::bind (sigc::mem_fun (*this, &SoundAsset::path_from_channel), files));
+}
+
+SoundAsset::SoundAsset (
+       sigc::slot<string, Channel> get_path, string mxf_path, sigc::signal1<void, float>* progress, int fps, int length, int channels
+       )
+       : Asset (mxf_path, progress, fps, length)
+       , _channels (channels)
+{
+       construct (get_path);
+}
+
+string
+SoundAsset::path_from_channel (Channel channel, vector<string> const & files)
+{
+       unsigned int const c = int (channel);
+       assert (c < files.size ());
+       return files[c];
+}
+
+void
+SoundAsset::construct (sigc::slot<string, Channel> get_path)
 {
        ASDCP::Rational asdcp_fps (_fps, 1);
        
-       ASDCP::PCM::WAVParser pcm_parser_channel[files.size()];
-       if (pcm_parser_channel[0].OpenRead (files.front().c_str(), asdcp_fps)) {
+       ASDCP::PCM::WAVParser pcm_parser_channel[_channels];
+       if (pcm_parser_channel[0].OpenRead (get_path(LEFT).c_str(), asdcp_fps)) {
                throw runtime_error ("could not open WAV file for reading");
        }
        
@@ -47,24 +73,33 @@ SoundAsset::SoundAsset (list<string> const & files, string mxf_path, sigc::signa
        audio_desc.ChannelCount = 0;
        audio_desc.BlockAlign = 0;
        audio_desc.EditRate = asdcp_fps;
-       audio_desc.AvgBps = audio_desc.AvgBps * files.size ();
+       audio_desc.AvgBps = audio_desc.AvgBps * _channels;
 
-       ASDCP::PCM::FrameBuffer frame_buffer_channel[files.size()];
-       ASDCP::PCM::AudioDescriptor audio_desc_channel[files.size()];
-       
-       int j = 0;
-       for (list<string>::const_iterator i = files.begin(); i != files.end(); ++i) {
+       Channel channels[] = {
+               LEFT,
+               RIGHT,
+               CENTRE,
+               LFE,
+               LS,
+               RS
+       };
+
+       ASDCP::PCM::FrameBuffer frame_buffer_channel[_channels];
+       ASDCP::PCM::AudioDescriptor audio_desc_channel[_channels];
+
+       for (int i = 0; i < _channels; ++i) {
+
+               string const path = get_path (channels[i]);
                
-               if (ASDCP_FAILURE (pcm_parser_channel[j].OpenRead (i->c_str(), asdcp_fps))) {
+               if (ASDCP_FAILURE (pcm_parser_channel[i].OpenRead (path.c_str(), asdcp_fps))) {
                        throw runtime_error ("could not open WAV file for reading");
                }
 
-               pcm_parser_channel[j].FillAudioDescriptor (audio_desc_channel[j]);
-               frame_buffer_channel[j].Capacity (ASDCP::PCM::CalcFrameBufferSize (audio_desc_channel[j]));
+               pcm_parser_channel[i].FillAudioDescriptor (audio_desc_channel[i]);
+               frame_buffer_channel[i].Capacity (ASDCP::PCM::CalcFrameBufferSize (audio_desc_channel[i]));
 
-               audio_desc.ChannelCount += audio_desc_channel[j].ChannelCount;
-               audio_desc.BlockAlign += audio_desc_channel[j].BlockAlign;
-               ++j;
+               audio_desc.ChannelCount += audio_desc_channel[i].ChannelCount;
+               audio_desc.BlockAlign += audio_desc_channel[i].BlockAlign;
        }
 
        ASDCP::PCM::FrameBuffer frame_buffer;
@@ -86,7 +121,7 @@ SoundAsset::SoundAsset (list<string> const & files, string mxf_path, sigc::signa
                byte_t sample_size = ASDCP::PCM::CalcSampleSize (audio_desc_channel[0]);
                int offset = 0;
 
-               for (list<string>::size_type j = 0; j < files.size(); ++j) {
+               for (int j = 0; j < _channels; ++j) {
                        memset (frame_buffer_channel[j].Data(), 0, frame_buffer_channel[j].Capacity());
                        if (ASDCP_FAILURE (pcm_parser_channel[j].ReadFrame (frame_buffer_channel[j]))) {
                                throw runtime_error ("could not read audio frame");
@@ -98,7 +133,7 @@ SoundAsset::SoundAsset (list<string> const & files, string mxf_path, sigc::signa
                }
 
                while (data_s < data_e) {
-                       for (list<string>::size_type j = 0; j < files.size(); ++j) {
+                       for (int j = 0; j < _channels; ++j) {
                                byte_t* frame = frame_buffer_channel[j].Data() + offset;
                                memcpy (data_s, frame, sample_size);
                                data_s += sample_size;
index c63bab90ccd391f49a7aeab8bb1d98c5176b0097..591b0a47ed158106ef813f3713ef683cc8736e98 100644 (file)
 
 */
 
+#ifndef LIBDCP_SOUND_ASSET_H
+#define LIBDCP_SOUND_ASSET_H
+
 /** @file  src/sound_asset.h
  *  @brief An asset made up of WAV files
  */
 
 #include "asset.h"
+#include "types.h"
 
 namespace libdcp
 {
@@ -37,13 +41,47 @@ public:
         *  @param progress Signal to inform of progress.
         *  @param fps Frames per second.
         *  @param length Length in frames.
+        *  @param channels Number of audio channels.
         */
-       SoundAsset (std::list<std::string> const & files, std::string mxf_path, sigc::signal1<void, float>* progress, int fps, int length);
+       SoundAsset (
+               std::vector<std::string> const & files,
+               std::string mxf_path,
+               sigc::signal1<void, float>* progress,
+               int fps,
+               int length
+               );
 
+       /** Construct a SoundAsset, generating the MXF from the WAV files.
+        *  This may take some time; progress is indicated by emission of the Progress signal.
+        *  @param files Pathnames of sound files, in the order Left, Right, Centre, Lfe (sub), Left surround, Right surround.
+        *  @param mxf_path Pathname of MXF file to create.
+        *  @param progress Signal to inform of progress.
+        *  @param fps Frames per second.
+        *  @param length Length in frames.
+        *  @param channels Number of audio channels.
+        */
+       SoundAsset (
+               sigc::slot<std::string, Channel>,
+               std::string mxf_path,
+               sigc::signal1<void, float>* progress,
+               int fps,
+               int length,
+               int channels
+               );
+       
        /** Write details of this asset to a CPL stream.
         *  @param s Stream.
         */
        void write_to_cpl (std::ostream& s) const;
+
+private:
+       void construct (sigc::slot<std::string, Channel> get_path);
+       std::string path_from_channel (Channel channel, std::vector<std::string> const & files);
+
+       /** Number of channels in the asset */
+       int _channels;
 };
 
 }
+
+#endif
diff --git a/src/types.h b/src/types.h
new file mode 100644 (file)
index 0000000..286c362
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+    Copyright (C) 2012 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_CHANNEL_H
+#define LIBDCP_CHANNEL_H
+
+namespace libdcp
+{
+
+/** Identifier for a sound channel */
+enum Channel {
+       LEFT = 0,    ///< left
+       RIGHT = 1,   ///< right
+       CENTRE = 2,  ///< centre
+       LFE = 3,     ///< low-frequency effects (sub)
+       LS = 4,      ///< left surround
+       RS = 5       ///< right surround
+};
+
+}
+
+#endif
index 7417dee55a1ddfef587d3b9eb1465f6f1bc73b15..db6906c81fa18ca446ff5a1a20e9103a0c8f13ea 100644 (file)
@@ -17,6 +17,7 @@ def build(bld):
     headers = """
               dcp.h
               metadata.h
+              types.h
               """
 
     bld.install_files('${PREFIX}/include/libdcp', headers)
index 7d60f70e5d159b4c09797369db87a2e295364972..f4e5b4415d023d78a6c1219734d30ad5fcde7e93 100644 (file)
@@ -22,6 +22,7 @@
 #include "dcp.h"
 #include "util.h"
 #include "metadata.h"
+#include "types.h"
 
 #define BOOST_TEST_DYN_LINK
 #define BOOST_TEST_MODULE libdcp_test
 using namespace std;
 using namespace boost;
 
+string
+j2c (int)
+{
+       return "test/data/32x32_red_square.j2c";
+}
+
+string
+wav (libdcp::Channel)
+{
+       return "test/data/1s_24-bit_48k_silence.wav";
+}
+               
+
 BOOST_AUTO_TEST_CASE (dcp_test)
 {
        Kumu::libdcp_test = true;
@@ -45,17 +59,8 @@ BOOST_AUTO_TEST_CASE (dcp_test)
        filesystem::create_directories ("build/test/foo");
        libdcp::DCP d ("build/test/foo", "A Test DCP", libdcp::DCP::FEATURE, 24, 24);
 
-       list<string> j2cs;
-       for (int i = 0; i < 24; ++i) {
-               j2cs.push_back ("test/data/32x32_red_square.j2c");
-       }
-       d.add_picture_asset (j2cs, 32, 32);
-       
-       list<string> wavs;
-       for (int i = 0; i < 2; ++i) {
-               wavs.push_back ("test/data/1s_24-bit_48k_silence.wav");
-       }
-       d.add_sound_asset (wavs);
+       d.add_picture_asset (sigc::ptr_fun (&j2c), 32, 32);
+       d.add_sound_asset (sigc::ptr_fun (&wav), 2);
 
        d.write_xml ();
 }